Index: xulrunner-1.9.0.11/content/events/public/nsIPrivateTextEvent.h
===================================================================
--- xulrunner-1.9.0.11.orig/content/events/public/nsIPrivateTextEvent.h	2005-11-11 21:35:54.000000000 +0700
+++ xulrunner-1.9.0.11/content/events/public/nsIPrivateTextEvent.h	2009-07-17 14:35:44.000000000 +0700
@@ -43,9 +43,9 @@
 #include "nsIPrivateTextRange.h"
 
 #define NS_IPRIVATETEXTEVENT_IID \
-{ /* 37B69251-4ACE-11d3-9EA6-0060089FE59B */ \
-0x37b69251, 0x4ace, 0x11d3, \
-{0x9e, 0xa6, 0x0, 0x60, 0x8, 0x9f, 0xe5, 0x9b} }
+{ /* 9644bf06-7109-11de-9efe-002215dcd99e */ \
+0x9644bf06, 0x7109, 0x11de, \
+{0x9e, 0xfe, 0x00, 0x22, 0x15, 0xdc, 0xd9, 0x9e} }
 
 class nsIPrivateTextEvent : public nsISupports {
 
@@ -55,6 +55,7 @@
 	NS_IMETHOD GetText(nsString& aText) = 0;
 	NS_IMETHOD GetInputRange(nsIPrivateTextRangeList** aInputRange) = 0;
 	NS_IMETHOD GetEventReply(struct nsTextEventReply** aReply) = 0;
+	NS_IMETHOD GetDeleteRange(PRInt32& aOffset, PRInt32& aNChars) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIPrivateTextEvent, NS_IPRIVATETEXTEVENT_IID)
Index: xulrunner-1.9.0.11/content/events/src/nsDOMEvent.cpp
===================================================================
--- xulrunner-1.9.0.11.orig/content/events/src/nsDOMEvent.cpp	2008-03-22 05:47:14.000000000 +0700
+++ xulrunner-1.9.0.11/content/events/src/nsDOMEvent.cpp	2009-07-17 14:35:44.000000000 +0700
@@ -61,6 +61,7 @@
   "mouseout", "mousemove", "contextmenu", "keydown", "keyup", "keypress",
   "focus", "blur", "load", "beforeunload", "unload", "abort", "error",
   "submit", "reset", "change", "select", "input", "paint" ,"text",
+  "getText", "deleteText",
   "compositionstart", "compositionend", "popupshowing", "popupshown",
   "popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate",
   "dragenter", "dragover", "dragexit", "dragdrop", "draggesture",
@@ -1239,6 +1240,10 @@
     return sEventNames[eDOMEvents_scroll];
   case NS_TEXT_TEXT:
     return sEventNames[eDOMEvents_text];
+  case NS_TEXT_GET_TEXT:
+    return sEventNames[eDOMEvents_getText];
+  case NS_TEXT_DELETE_TEXT:
+    return sEventNames[eDOMEvents_deleteText];
   case NS_XUL_POPUP_SHOWING:
     return sEventNames[eDOMEvents_popupShowing];
   case NS_XUL_POPUP_SHOWN:
Index: xulrunner-1.9.0.11/content/events/src/nsDOMEvent.h
===================================================================
--- xulrunner-1.9.0.11.orig/content/events/src/nsDOMEvent.h	2008-03-22 05:47:14.000000000 +0700
+++ xulrunner-1.9.0.11/content/events/src/nsDOMEvent.h	2009-07-17 14:35:44.000000000 +0700
@@ -86,6 +86,8 @@
     eDOMEvents_input,
     eDOMEvents_paint,
     eDOMEvents_text,
+    eDOMEvents_getText,
+    eDOMEvents_deleteText,
     eDOMEvents_compositionstart,
     eDOMEvents_compositionend,
     eDOMEvents_popupShowing,
Index: xulrunner-1.9.0.11/content/events/src/nsDOMTextEvent.cpp
===================================================================
--- xulrunner-1.9.0.11.orig/content/events/src/nsDOMTextEvent.cpp	2007-07-08 14:08:07.000000000 +0700
+++ xulrunner-1.9.0.11/content/events/src/nsDOMTextEvent.cpp	2009-07-17 14:35:44.000000000 +0700
@@ -82,6 +82,10 @@
       }
     }
   }
+
+  // set delete surrounding range
+  mDeleteOffset = te->offset;
+  mDeleteNChars = te->nChars;
 }
 
 NS_IMPL_ADDREF_INHERITED(nsDOMTextEvent, nsDOMUIEvent)
@@ -99,7 +103,8 @@
 
 NS_METHOD nsDOMTextEvent::GetInputRange(nsIPrivateTextRangeList** aInputRange)
 {
-  if (mEvent->message == NS_TEXT_TEXT)
+  if (mEvent->message == NS_TEXT_TEXT ||
+      mEvent->message == NS_TEXT_GET_TEXT)
   {
     *aInputRange = mTextRange;
     NS_IF_ADDREF(*aInputRange);
@@ -111,7 +116,8 @@
 
 NS_METHOD nsDOMTextEvent::GetEventReply(nsTextEventReply** aReply)
 {
-  if (mEvent->message == NS_TEXT_TEXT)
+  if (mEvent->message == NS_TEXT_TEXT ||
+      mEvent->message == NS_TEXT_GET_TEXT)
   {
      *aReply = &(static_cast<nsTextEvent*>(mEvent)->theReply);
      return NS_OK;
@@ -120,6 +126,20 @@
   return NS_ERROR_FAILURE;
 }
 
+NS_METHOD nsDOMTextEvent::GetDeleteRange(PRInt32& aOffset,
+                                         PRInt32& aNChars)
+{
+  if (mEvent->message == NS_TEXT_DELETE_TEXT)
+  {
+     aOffset = mDeleteOffset;
+     aNChars = mDeleteNChars;
+     return NS_OK;
+  }
+  aOffset = 0;
+  aNChars = 0;
+  return NS_ERROR_FAILURE;
+}
+
 nsresult NS_NewDOMTextEvent(nsIDOMEvent** aInstancePtrResult,
                             nsPresContext* aPresContext,
                             nsTextEvent *aEvent)
Index: xulrunner-1.9.0.11/content/events/src/nsDOMTextEvent.h
===================================================================
--- xulrunner-1.9.0.11.orig/content/events/src/nsDOMTextEvent.h	2007-01-04 17:32:09.000000000 +0700
+++ xulrunner-1.9.0.11/content/events/src/nsDOMTextEvent.h	2009-07-17 14:35:44.000000000 +0700
@@ -58,10 +58,13 @@
   NS_IMETHOD GetText(nsString& aText);
   NS_IMETHOD GetInputRange(nsIPrivateTextRangeList** aInputRange);
   NS_IMETHOD GetEventReply(nsTextEventReply** aReply);
+  NS_IMETHOD GetDeleteRange(PRInt32& aOffset, PRInt32& aNChars);
   
 protected:
   nsString mText;
   nsRefPtr<nsPrivateTextRangeList> mTextRange;
+  PRInt32 mDeleteOffset;
+  PRInt32 mDeleteNChars;
 };
 
 #endif // nsDOMTextEvent_h__
Index: xulrunner-1.9.0.11/content/events/src/nsEventListenerManager.cpp
===================================================================
--- xulrunner-1.9.0.11.orig/content/events/src/nsEventListenerManager.cpp	2008-08-15 15:49:31.000000000 +0700
+++ xulrunner-1.9.0.11/content/events/src/nsEventListenerManager.cpp	2009-07-17 14:35:44.000000000 +0700
@@ -233,7 +233,9 @@
 };
 
 static const EventDispatchData sTextEvents[] = {
-  { NS_TEXT_TEXT, HANDLER(&nsIDOMTextListener::HandleText) }
+  { NS_TEXT_TEXT,        HANDLER(&nsIDOMTextListener::HandleText) },
+  { NS_TEXT_GET_TEXT,    HANDLER(&nsIDOMTextListener::GetText)    },
+  { NS_TEXT_DELETE_TEXT, HANDLER(&nsIDOMTextListener::DeleteText) }
 };
 
 static const EventDispatchData sKeyEvents[] = {
Index: xulrunner-1.9.0.11/dom/public/coreEvents/nsIDOMTextListener.h
===================================================================
--- xulrunner-1.9.0.11.orig/dom/public/coreEvents/nsIDOMTextListener.h	2005-11-11 21:35:58.000000000 +0700
+++ xulrunner-1.9.0.11/dom/public/coreEvents/nsIDOMTextListener.h	2009-07-17 14:35:44.000000000 +0700
@@ -56,6 +56,8 @@
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOMTEXTLISTENER_IID)
 
   NS_IMETHOD HandleText(nsIDOMEvent* aTextEvent) = 0;
+  NS_IMETHOD GetText(nsIDOMEvent* aTextEvent) = 0;
+  NS_IMETHOD DeleteText(nsIDOMEvent* aTextEvent) = 0;
 
 };
 
Index: xulrunner-1.9.0.11/editor/idl/nsIEditorIMESupport.idl
===================================================================
--- xulrunner-1.9.0.11.orig/editor/idl/nsIEditorIMESupport.idl	2008-02-20 14:18:53.000000000 +0700
+++ xulrunner-1.9.0.11/editor/idl/nsIEditorIMESupport.idl	2009-07-17 14:35:44.000000000 +0700
@@ -52,7 +52,7 @@
 [ptr] native nsQueryCaretRectEventReplyPtr(nsQueryCaretRectEventReply);
 
 
-[scriptable, uuid(ce1c0424-c3c0-44b0-97d6-df12deb19d45)]
+[scriptable, uuid(d05d34f6-710a-11de-b6ff-002215dcd99e)]
 
 interface nsIEditorIMESupport : nsISupports
 {
@@ -114,6 +114,18 @@
   [noscript] void getQueryCaretRect(in nsQueryCaretRectEventReplyPtr aReply);
 
   /**
+   * retrieveSurrounding()  Retrieve the surrounding text
+   */
+
+  [noscript] void retrieveSurrounding(in nsTextEventReplyPtr aReply);
+
+  /**
+   * deleteSurrounding()  Delete the surrounding text
+   */
+
+  [noscript] void deleteSurrounding(in PRInt32 aOffset, in PRInt32 aNChars);
+
+  /**
    * Get preferred IME status of current widget.
    */
 
Index: xulrunner-1.9.0.11/editor/libeditor/base/nsEditor.cpp
===================================================================
--- xulrunner-1.9.0.11.orig/editor/libeditor/base/nsEditor.cpp	2009-03-18 05:47:50.000000000 +0700
+++ xulrunner-1.9.0.11/editor/libeditor/base/nsEditor.cpp	2009-07-17 14:35:44.000000000 +0700
@@ -2156,6 +2156,18 @@
 }
 
 NS_IMETHODIMP
+nsEditor::RetrieveSurrounding(nsTextEventReply* aReply)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsEditor::DeleteSurrounding(PRInt32 aOffset, PRInt32 aNChars)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 nsEditor::GetPreferredIMEState(PRUint32 *aState)
 {
   NS_ENSURE_ARG_POINTER(aState);
Index: xulrunner-1.9.0.11/editor/libeditor/text/nsEditorEventListeners.cpp
===================================================================
--- xulrunner-1.9.0.11.orig/editor/libeditor/text/nsEditorEventListeners.cpp	2008-04-18 20:29:57.000000000 +0700
+++ xulrunner-1.9.0.11/editor/libeditor/text/nsEditorEventListeners.cpp	2009-07-17 14:35:44.000000000 +0700
@@ -480,6 +480,47 @@
    return result;
 }
 
+nsresult
+nsTextEditorTextListener::GetText(nsIDOMEvent* aTextEvent)
+{
+   nsCOMPtr<nsIPrivateTextEvent> textEvent = do_QueryInterface(aTextEvent);
+   if (!textEvent) {
+      //non-ui event passed in.  bad things.
+      return NS_OK;
+   }
+
+   nsresult result;
+   nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(mEditor, &result);
+   if (imeEditor) {
+      nsTextEventReply *textEventReply;
+
+      textEvent->GetEventReply(&textEventReply);
+      result = imeEditor->RetrieveSurrounding(textEventReply);
+   }
+
+   return result;
+}
+
+nsresult
+nsTextEditorTextListener::DeleteText(nsIDOMEvent* aTextEvent)
+{
+   nsCOMPtr<nsIPrivateTextEvent> textEvent = do_QueryInterface(aTextEvent);
+   if (!textEvent) {
+     //non-ui event passed in.  bad things.
+     return NS_OK;
+   }
+
+   nsresult result;
+   nsCOMPtr<nsIEditorIMESupport> imeEditor = do_QueryInterface(mEditor, &result);
+   if (imeEditor) {
+     PRInt32 offset, nChars;
+     textEvent->GetDeleteRange(offset, nChars);
+     result = imeEditor->DeleteSurrounding(offset, nChars);
+   }
+
+   return result;
+}
+
 /*
  * nsTextEditorDragListener implementation
  */
Index: xulrunner-1.9.0.11/editor/libeditor/text/nsEditorEventListeners.h
===================================================================
--- xulrunner-1.9.0.11.orig/editor/libeditor/text/nsEditorEventListeners.h	2008-04-16 01:40:41.000000000 +0700
+++ xulrunner-1.9.0.11/editor/libeditor/text/nsEditorEventListeners.h	2009-07-17 14:35:44.000000000 +0700
@@ -114,6 +114,8 @@
 /*BEGIN implementations of textevent handler interface*/
     NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
     NS_IMETHOD HandleText(nsIDOMEvent* aTextEvent);
+    NS_IMETHOD GetText(nsIDOMEvent* aTextEvent);
+    NS_IMETHOD DeleteText(nsIDOMEvent* aTextEvent);
 /*END implementations of textevent handler interface*/
 
 protected:
Index: xulrunner-1.9.0.11/editor/libeditor/text/nsPlaintextEditor.cpp
===================================================================
--- xulrunner-1.9.0.11.orig/editor/libeditor/text/nsPlaintextEditor.cpp	2008-04-15 08:04:18.000000000 +0700
+++ xulrunner-1.9.0.11/editor/libeditor/text/nsPlaintextEditor.cpp	2009-07-17 14:38:07.000000000 +0700
@@ -1781,6 +1781,104 @@
   return DeleteSelection(eNone);
 }
 
+NS_IMETHODIMP 
+nsPlaintextEditor::RetrieveSurrounding(nsTextEventReply* aReply)
+{
+  nsresult result;
+
+  nsCOMPtr<nsISelection> selection;
+  result = GetSelection(getter_AddRefs(selection));
+  if (NS_FAILED(result))
+    return result;
+
+  nsCOMPtr<nsIDOMNode> startNode;
+  result = GetStartNodeAndOffset(selection,
+                                 address_of(startNode),
+                                 &aReply->cursorPos);
+  if (NS_FAILED(result))
+    return result;
+
+  result = startNode->GetNodeValue(aReply->theText);
+
+  return result;
+}
+
+NS_IMETHODIMP
+nsPlaintextEditor::DeleteSurrounding(const PRInt32 aOffset,
+                                     const PRInt32 aNChars)
+{
+  nsresult result;
+  nsCOMPtr<nsISelection> selection;
+  result = GetSelection(getter_AddRefs(selection));
+  if (NS_FAILED(result))
+    return result;
+
+  // The following code was mostly borrowed from GetTextSelectionOffsets
+  nsCOMPtr<nsIDOMNode> startNode, endNode, parentNode;
+  PRInt32 endOffset;
+  selection->GetAnchorNode(getter_AddRefs(startNode));
+  selection->GetFocusNode(getter_AddRefs(endNode));
+  selection->GetFocusOffset(&endOffset);
+
+  nsCOMPtr<nsIEnumerator> enumerator;
+  nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(selection));
+  result = selPriv->GetEnumerator(getter_AddRefs(enumerator));
+  if (NS_FAILED(result))
+    return result;
+  if (!enumerator)
+    return NS_ERROR_NULL_POINTER;
+
+  // don't use "result" in this block
+  enumerator->First(); 
+  nsCOMPtr<nsISupports> currentItem;
+  nsresult findParentResult = enumerator->CurrentItem(getter_AddRefs(currentItem));
+  if ((NS_SUCCEEDED(findParentResult)) && (currentItem))
+  {
+    nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
+    range->GetCommonAncestorContainer(getter_AddRefs(parentNode));
+  }
+  else 
+  {
+    parentNode = do_QueryInterface(startNode);
+  }
+
+  // The following code was mostly borrowed from GetAbsoluteOffsetsForPoints
+  nsCOMPtr<nsIContentIterator> iter = do_CreateInstance(
+                     "@mozilla.org/content/post-content-iterator;1", &result);
+  if (NS_FAILED(result))
+    return result;
+  if (!iter)
+    return NS_ERROR_NULL_POINTER;
+    
+  PRUint32 totalLength=0;
+  nsCOMPtr<nsIDOMCharacterData>textNode;
+  nsCOMPtr<nsIContent>blockParentContent = do_QueryInterface(parentNode);
+  iter->Init(blockParentContent);
+  // loop through the content iterator for each content node
+  while (!iter->IsDone())
+  {
+    textNode = do_QueryInterface(iter->GetCurrentNode());
+    if (textNode)
+    {
+      nsCOMPtr<nsIDOMNode>currentNode = do_QueryInterface(textNode);
+      if (!currentNode) {return NS_ERROR_NO_INTERFACE;}
+      if (IsEditable(currentNode))
+      {
+        if (currentNode.get() == endNode)
+        {
+          return DeleteText(textNode, totalLength + endOffset + aOffset, aNChars);
+        }
+      }
+      PRUint32 length;
+      textNode->GetLength(&length);
+      totalLength += length;
+    }
+    iter->Next();
+  }
+
+  return NS_ERROR_FAILURE;
+}
+
 #ifdef XP_MAC
 #pragma mark -
 #pragma mark  nsEditor overrides 
Index: xulrunner-1.9.0.11/editor/libeditor/text/nsPlaintextEditor.h
===================================================================
--- xulrunner-1.9.0.11.orig/editor/libeditor/text/nsPlaintextEditor.h	2007-09-30 00:56:05.000000000 +0700
+++ xulrunner-1.9.0.11/editor/libeditor/text/nsPlaintextEditor.h	2009-07-17 14:35:44.000000000 +0700
@@ -89,6 +89,8 @@
   
   NS_IMETHOD SetCompositionString(const nsAString & aCompositionString, nsIPrivateTextRangeList * aTextRange, nsTextEventReply * aReply);
   NS_IMETHOD GetReconversionString(nsReconversionEventReply* aReply);
+  NS_IMETHOD RetrieveSurrounding(nsTextEventReply* aReply);
+  NS_IMETHOD DeleteSurrounding(PRInt32 aOffset, PRInt32 aNChars);
 
   /* ------------ Overrides of nsEditor interface methods -------------- */
   NS_IMETHOD BeginComposition(nsTextEventReply* aReply);
Index: xulrunner-1.9.0.11/widget/public/nsGUIEvent.h
===================================================================
--- xulrunner-1.9.0.11.orig/widget/public/nsGUIEvent.h	2008-04-18 05:38:35.000000000 +0700
+++ xulrunner-1.9.0.11/widget/public/nsGUIEvent.h	2009-07-17 14:35:44.000000000 +0700
@@ -299,6 +299,8 @@
 // text events
 #define NS_TEXT_START                 2400
 #define NS_TEXT_TEXT                  (NS_TEXT_START)
+#define NS_TEXT_GET_TEXT              (NS_TEXT_START + 1)
+#define NS_TEXT_DELETE_TEXT           (NS_TEXT_START + 2)
 
 // UI events
 #define NS_UI_EVENT_START          2500
@@ -765,6 +767,8 @@
 
   nsRect mCursorPosition;
   PRBool mCursorIsCollapsed;
+  nsAutoString theText;
+  PRInt32      cursorPos;
 };
 
 typedef struct nsTextEventReply nsTextEventReply;
@@ -774,7 +778,8 @@
 public:
   nsTextEvent(PRBool isTrusted, PRUint32 msg, nsIWidget *w)
     : nsInputEvent(isTrusted, msg, w, NS_TEXT_EVENT),
-      theText(nsnull), rangeCount(0), rangeArray(nsnull), isChar(PR_FALSE)
+      theText(nsnull), rangeCount(0), rangeArray(nsnull), isChar(PR_FALSE),
+      offset(0), nChars(0)
   {
   }
 
@@ -783,6 +788,8 @@
   PRUint32          rangeCount;
   nsTextRangeArray  rangeArray;
   PRBool            isChar;
+  PRInt32           offset;
+  PRInt32           nChars;
 };
 
 class nsCompositionEvent : public nsInputEvent
@@ -1089,6 +1096,8 @@
 
 #define NS_IS_IME_EVENT(evnt) \
        (((evnt)->message == NS_TEXT_TEXT) ||  \
+        ((evnt)->message == NS_TEXT_GET_TEXT) ||  \
+        ((evnt)->message == NS_TEXT_DELETE_TEXT) ||  \
         ((evnt)->message == NS_COMPOSITION_START) ||  \
         ((evnt)->message == NS_COMPOSITION_END) || \
         ((evnt)->message == NS_RECONVERSION_QUERY) || \
Index: xulrunner-1.9.0.11/widget/src/gtk2/nsWindow.cpp
===================================================================
--- xulrunner-1.9.0.11.orig/widget/src/gtk2/nsWindow.cpp	2009-04-20 10:17:56.000000000 +0700
+++ xulrunner-1.9.0.11/widget/src/gtk2/nsWindow.cpp	2009-07-17 14:35:44.000000000 +0700
@@ -269,6 +269,12 @@
                                        nsWindow *aWindow);
 static void IM_preedit_changed_cb     (GtkIMContext *aContext,
                                        nsWindow *aWindow);
+static gboolean IM_retrieve_surrounding_cb(GtkIMContext *aContext,
+                                           nsWindow     *aWindow);
+static gboolean IM_delete_surrounding_cb  (GtkIMContext *aContext,
+                                           gint          aOffset,
+                                           gint          aNChars,
+                                           nsWindow     *aWindow);
 static void IM_set_text_range         (const PRInt32 aLen,
                                        const gchar *aPreeditString,
                                        const gint aCursorPos,
@@ -5731,10 +5737,18 @@
 
     g_signal_connect(G_OBJECT(mIMEData->mContext), "preedit_changed",
                      G_CALLBACK(IM_preedit_changed_cb), this);
+    g_signal_connect(G_OBJECT(mIMEData->mContext), "retrieve_surrounding",
+                     G_CALLBACK(IM_retrieve_surrounding_cb), this);
+    g_signal_connect(G_OBJECT(mIMEData->mContext), "delete_surrounding",
+                     G_CALLBACK(IM_delete_surrounding_cb), this);
     g_signal_connect(G_OBJECT(mIMEData->mContext), "commit",
                      G_CALLBACK(IM_commit_cb), this);
     g_signal_connect(G_OBJECT(mIMEData->mSimpleContext), "preedit_changed",
                      G_CALLBACK(IM_preedit_changed_cb), this);
+    g_signal_connect(G_OBJECT(mIMEData->mSimpleContext), "retrieve_surrounding",
+                     G_CALLBACK(IM_retrieve_surrounding_cb), this);
+    g_signal_connect(G_OBJECT(mIMEData->mSimpleContext), "delete_surrounding",
+                     G_CALLBACK(IM_delete_surrounding_cb), this);
     g_signal_connect(G_OBJECT(mIMEData->mSimpleContext), "commit",
                      G_CALLBACK(IM_commit_cb), this);
 }
@@ -5774,6 +5788,43 @@
     return retval;
 }
 
+void
+nsWindow::IMEGetText(PRUnichar* &aText,
+                     PRInt32&    aLength,
+                     PRInt32&    aCursorPos)
+{
+    nsTextEvent textEvent(PR_TRUE, NS_TEXT_GET_TEXT, this);
+    nsEventStatus status;
+    const PRUnichar *text;
+    PRInt32 i;
+
+    aText = nsnull;
+    aLength = 0;
+    aCursorPos = 0;
+
+    DispatchEvent(&textEvent, status);
+    aLength = textEvent.theReply.theText.Length();
+    aText = reinterpret_cast<PRUnichar*>(nsMemory::Alloc(sizeof (PRUnichar) * (aLength + 1)));
+    text = textEvent.theReply.theText.get();
+    aCursorPos = textEvent.theReply.cursorPos;
+    for (i = 0; i < aLength; i++) {
+        aText[i] = text[i];
+    }
+    aText[i] = 0;
+}
+
+void
+nsWindow::IMEDeleteText(const PRInt32 aOffset,
+                        const PRInt32 aNChars)
+{
+    nsTextEvent textEvent(PR_TRUE, NS_TEXT_DELETE_TEXT, this);
+    nsEventStatus status;
+
+    textEvent.offset = aOffset;
+    textEvent.nChars = aNChars;
+    DispatchEvent(&textEvent, status);
+}
+
 /* nsIKBStateControl */
 NS_IMETHODIMP
 nsWindow::ResetInputState()
@@ -5974,6 +6025,52 @@
 }
 
 /* static */
+gboolean
+IM_retrieve_surrounding_cb(GtkIMContext *aContext,
+                           nsWindow     *aWindow)
+{
+    PRUnichar *uniStr = NULL;
+    PRInt32 uniStrLength, cursorPos;
+    nsWindow *window = gFocusWindow ? gFocusWindow : gIMEFocusWindow;
+    gchar *utf8_str, *p;
+    glong wbytes;
+
+    window->IMEGetText(uniStr, uniStrLength, cursorPos);
+    if (uniStr != NULL) {
+        utf8_str = g_utf16_to_utf8((const gunichar2 *)uniStr, uniStrLength, NULL, &wbytes, NULL);
+        nsMemory::Free(uniStr);
+        if (utf8_str == NULL) {
+            LOGIM(("failed to convert utf16 string to utf8!\n"));
+            return FALSE;
+        }
+        utf8_str[wbytes] = 0;
+        p = utf8_str;
+        while (cursorPos > 0 && *p != 0) {
+            p = g_utf8_next_char(p);
+            cursorPos--;
+        }
+        gtk_im_context_set_surrounding(aContext, utf8_str, -1, p - utf8_str);
+        g_free(utf8_str);
+    }
+
+    return TRUE;
+}
+
+/* static */
+gboolean
+IM_delete_surrounding_cb(GtkIMContext *aContext,
+                         gint          aOffset,
+                         gint          aNChars,
+                         nsWindow     *aWindow)
+{
+    nsWindow *window = gFocusWindow ? gFocusWindow : gIMEFocusWindow;
+
+    window->IMEDeleteText(aOffset, aNChars);
+
+    return TRUE;
+}
+
+/* static */
 void
 IM_commit_cb(GtkIMContext *aContext,
              const gchar  *aUtf8_str,
Index: xulrunner-1.9.0.11/widget/src/gtk2/nsWindow.h
===================================================================
--- xulrunner-1.9.0.11.orig/widget/src/gtk2/nsWindow.h	2009-04-20 10:17:55.000000000 +0700
+++ xulrunner-1.9.0.11/widget/src/gtk2/nsWindow.h	2009-07-17 14:35:44.000000000 +0700
@@ -294,6 +294,11 @@
     nsWindow*          IMEComposingWindow(void);
     void               IMECreateContext  (void);
     PRBool             IMEFilterEvent    (GdkEventKey *aEvent);
+    void               IMEGetText        (PRUnichar* &aText,
+                                          PRInt32&    aLength,
+                                          PRInt32&    aCursorPos);
+    void               IMEDeleteText     (const PRInt32 aOffset,
+                                          const PRInt32 aNChars);
 
     /*
      *  |mIMEData| has all IME data for the window and its children widgets.
