Example #1
0
//IDropTarget methods
STDMETHODIMP CDropTarget::DragEnter(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
#ifdef _DEBUG
	printf("IDropTarget::DragEnter\n");
#endif //_DEBUG
	pDataObj = pDataObject;
	pDataObject->AddRef();
	hdrop_present = false;
	if (hexwnd.prefer_CF_HDROP)
	{
		FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, 0xffffffff };
		STGMEDIUM stm;
		if (S_OK == pDataObject->QueryGetData(&fe))
		{
			hdrop_present = true;
			*pdwEffect = DROPEFFECT_COPY;
			return S_OK;
		}
		else if (S_OK == pDataObject->GetData(&fe, &stm))
		{
			hdrop_present = true;
			ReleaseStgMedium(&stm);
			*pdwEffect = DROPEFFECT_COPY;
			return S_OK;
		}
	}

	hexwnd.pwnd->CreateCaret((HBITMAP)1, 2, hexwnd.cyChar);

	return DragOver(grfKeyState, pt, pdwEffect);
}
nsresult
EditorEventListener::DragEnter(nsIDOMDragEvent* aDragEvent)
{
  NS_ENSURE_TRUE(aDragEvent, NS_OK);

  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
  NS_ENSURE_TRUE(presShell, NS_OK);

  if (!mCaret) {
    mCaret = new nsCaret();
    mCaret->Init(presShell);
    mCaret->SetCaretReadOnly(true);
    // This is to avoid the requirement that the Selection is Collapsed which
    // it can't be when dragging a selection in the same shell.
    // See nsCaret::IsVisible().
    mCaret->SetVisibilityDuringSelection(true);
  }

  presShell->SetCaret(mCaret);

  return DragOver(aDragEvent);
}
Example #3
0
HRESULT STDMETHODCALLTYPE CDropTarget::DragEnter( IDataObject *pData, DWORD fKeyState, POINTL pt, DWORD *pdwEffect)
{
	FORMATETC	feFile	 = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
	FORMATETC	feText	 = { CF_TEXT, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };

	if ( S_OK == pData->QueryGetData( &feFile ) ||
		 S_OK == pData->QueryGetData( &feText ))
	{
		POINT shortPt;
		shortPt.x = pt.x; 
		shortPt.y = pt.y;
		
		HWND hwnd = WindowFromPoint( shortPt );
		
		ThumbInfo *pThumb = thumbList.FindThumb(hwnd);
		if (pThumb)
		{
			hwndCurDrag = hwnd;
			pThumb->ThumbSelect( TRUE );
		}
	}

	return DragOver( fKeyState, pt, pdwEffect);
}
Example #4
0
STDMETHODIMP CDropTarget::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
{
#ifdef _DEBUG
	printf("IDropTarget::Drop\n");
#endif //_DEBUG

	DWORD dwOKEffects = *pdwEffect;
	{
		//We do this because grfKeyState will always have the mouse button used off
		DWORD temp = LastKeyState;
		//Get the position of the drop
		DragOver(grfKeyState, pt, pdwEffect);
		LastKeyState = temp;
	}
	//Remove the effects
	pDataObj = NULL;
	DragLeave();

	bool copying = (*pdwEffect & DROPEFFECT_COPY) != 0;

	size_t totallen = 0;
	BYTE *data = NULL;
	bool gotdata = false;

	UINT *formats = NULL;
	UINT numformats = 0;

	FORMATETC *fel = NULL;
	UINT numfe = 0;

	bool NeedToChooseFormat = true;
	int IndexOfDataToInsert = -1;
	bool NeedToChooseMoveorCopy = (LastKeyState | grfKeyState) & (MK_MBUTTON | MK_RBUTTON) || hexwnd.always_pick_move_copy;

	if (hexwnd.dragging) // Internal data
	{
		hexwnd.dragging = FALSE;
		if (NeedToChooseMoveorCopy)
		{
			int choice = PopupDropMenu(pt);
			if (choice == 0)
			{
				pDataObject->Release();
				*pdwEffect = DROPEFFECT_NONE;
				return S_OK;
			}
			copying = choice != 1;
		}
		int iMove1stEnd = hexwnd.iGetStartOfSelection();
		int iMove2ndEndorLen = hexwnd.iGetEndOfSelection();
		int iMovePosOrg = hexwnd.new_pos;
		if (!copying && hexwnd.new_pos > iMove2ndEndorLen)
			hexwnd.new_pos += iMove1stEnd - iMove2ndEndorLen - 1;
		iMovePos = hexwnd.new_pos;
		iMoveOpTyp = copying ? OPTYP_COPY : OPTYP_MOVE;
		SimpleArray<BYTE> olddata;
		const int len = iMove2ndEndorLen - iMove1stEnd + 1;
		if (grfKeyState & MK_SHIFT) // Overwrite
		{
			if (copying)
			{
				//Just [realloc &] memmove
				if (iMovePos + len > hexwnd.m_dataArray.GetLength()) // Need more space
				{
					olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], hexwnd.m_dataArray.GetLength() - iMovePos);
					if (hexwnd.m_dataArray.SetSize(iMovePos + len))
					{
						hexwnd.m_dataArray.ExpandToSize();
						memmove(&hexwnd.m_dataArray[iMovePos], &hexwnd.m_dataArray[iMove1stEnd], len);
					}
				}
				else // Enough space
				{
					olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], len);
					memmove(&hexwnd.m_dataArray[iMovePos], &hexwnd.m_dataArray[iMove1stEnd], len);
				}
				hexwnd.push_undorecord(iMovePos, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMovePos], len);
			}
			else //Moving
			{
				if (iMovePos > iMove1stEnd) //Forward
				{
					olddata.AppendArray(&hexwnd.m_dataArray[iMove1stEnd], iMovePosOrg + len - iMove1stEnd);
					hexwnd.move_copy_sub(iMove1stEnd, iMove2ndEndorLen, 0);
					hexwnd.m_dataArray.RemoveAt(iMovePos+len,len);
					hexwnd.push_undorecord(iMove1stEnd, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMove1stEnd], iMovePosOrg - iMove1stEnd);
				}
				else //Backward
				{
					if (iMove1stEnd-iMovePos>=len)
					{
						olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], iMove1stEnd + len - iMovePos);
						memmove(&hexwnd.m_dataArray[iMovePos],&hexwnd.m_dataArray[iMove1stEnd],len);
						hexwnd.m_dataArray.RemoveAt(iMove1stEnd,len);
					}
					else
					{
						olddata.AppendArray(&hexwnd.m_dataArray[iMovePos], iMove1stEnd + len - (iMovePos + len - iMove1stEnd) - iMovePos);
						memmove(&hexwnd.m_dataArray[iMovePos],&hexwnd.m_dataArray[iMove1stEnd],len);
						hexwnd.m_dataArray.RemoveAt(iMovePos+len,len-(iMovePos + len - iMove1stEnd));
					}
					hexwnd.push_undorecord(iMovePos, olddata, olddata.GetLength(), &hexwnd.m_dataArray[iMovePos], iMove1stEnd - iMovePos);
				}
			}
			hexwnd.iStartOfSelection = iMovePos;
			hexwnd.iEndOfSelection = iMovePos+len-1;
			hexwnd.bFilestatusChanged = true;
			hexwnd.bSelected = true;
			hexwnd.resize_window();
		}
		else // Insert
		{
			hexwnd.CMD_move_copy(iMove1stEnd, iMove2ndEndorLen, 1);
		}
	}
	else // External data
	{
		STGMEDIUM stm;
		HRESULT err = E_UNEXPECTED;

		//Get the formats enumerator
		IEnumFORMATETC *iefe = 0;
		pDataObject->EnumFormatEtc(DATADIR_GET, &iefe);
		if (iefe == 0)
		{
#ifdef _DEBUG
			printf("Unable to create a drag-drop data enumerator\n");
#endif //_DEBUG
			goto ERR;
		}
		iefe->Reset();

		//Get the available formats
		for(;;)
		{
			void *temp = realloc(fel, (numfe + 1) * sizeof(FORMATETC));
			if (temp != NULL)
			{
				fel = (FORMATETC*) temp;
				temp = NULL;
				int r;
				r = iefe->Next(1, &fel[numfe], NULL);
				if (r != S_OK)
					break;//No more formats
				numfe++;
			}
			else if (fel == NULL)
			{
				//We only go here if nothing could be allocated
#ifdef _DEBUG
				printf("Not enough memory for the drag-drop format list\n");
#endif //_DEBUG
				goto ERR_ENUM;
			}
		}
		UINT i;
		/*Check which format should be inserted according to user preferences*/
		if (numfe == 0)
		{
			MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_NO_DATA), MB_OK);
			err = S_OK;
			*pdwEffect = DROPEFFECT_NONE;
			goto ERR_ENUM;
		}
		if (hexwnd.prefer_CF_HDROP)
		{
			for (i = 0 ; i < numfe ; i++)
			{
				if (fel[i].cfFormat == CF_HDROP)
				{
					//Return no effect & let shell32 handle it
					if (S_OK == pDataObject->GetData(&fel[i], &stm))
					{
						hexwnd.dropfiles((HDROP)stm.hGlobal);
					}
					err = S_OK;
					*pdwEffect = DROPEFFECT_NONE;
					goto ERR_ENUM;
				}
			}
		}
		if (numfe == 1)
		{
			IndexOfDataToInsert = 0;
		}
		else if (hexwnd.prefer_CF_BINARYDATA)
		{
			for (i = 0 ; i < numfe ; i++)
			{
				if (fel[i].cfFormat == CF_BINARYDATA)
				{
					NeedToChooseFormat = false;
					IndexOfDataToInsert = i;
					break;
				}
			}
		}
		else if (hexwnd.prefer_CF_TEXT)
		{
			for (i = 0 ; i < numfe ; i++)
			{
				if (fel[i].cfFormat == CF_TEXT)
				{
					NeedToChooseFormat = false;
					IndexOfDataToInsert = i;
					break;
				}
			}
		}
		if (NeedToChooseFormat)
		{
			dialog<DragDropDlg> params;
			params.allowable_effects = dwOKEffects & (DROPEFFECT_COPY | DROPEFFECT_MOVE);
			params.effect = copying;
			params.formatetcs = fel;
			params.numformatetcs = numfe;
			params.formats = NULL;
			params.numformats = 0;
			int ret = params.DoModal(hexwnd.pwnd);
			if (ret < 0)
			{
				//An error occured or the user canceled the operation
				err = S_OK;
				*pdwEffect = DROPEFFECT_NONE;
				goto ERR_ENUM;
			}
			numformats = params.numformats;
			formats = params.formats;
			copying = params.effect;
		}
		else if (NeedToChooseMoveorCopy)
		{
			int choice = PopupDropMenu(pt);
			if (choice == 0)
			{
				err = S_OK;
				*pdwEffect = DROPEFFECT_NONE;
				goto ERR_ENUM;
			}
			copying = choice != 1;
		}

		if (IndexOfDataToInsert >= 0 && formats == NULL)
		{
			formats = (UINT*)&IndexOfDataToInsert;
			numformats = 1;
		}

		//for each selected format
		for (i = 0 ; i < numformats ; i++)
		{
			FORMATETC fe = fel[formats[i]];
			/*It is important that when debugging (with M$VC at least) you do not step __into__ the below GetData call
			  If you do the app providing the data source will die & GetData will return OLE_E_NOTRUNNING or E_FAIL
			  The solution is to step over the call
			  It is also possible that a debugger will be opened & attach itself to the data provider
			*/
			if (pDataObject->GetData(&fe, &stm) == S_OK)
			{
				//Get len
				size_t len = 0;
				switch (stm.tymed)
				{
					case TYMED_HGLOBAL:
						len = GlobalSize(stm.hGlobal);
						break;
#ifndef __CYGWIN__
					case TYMED_FILE:
					{
						int fh = _wopen(stm.lpszFileName, _O_BINARY | _O_RDONLY);
						if (fh != -1)
						{
							len = _filelength(fh);
							if (len == (size_t)-1)
								len = 0;
							_close(fh);
						}
					} break;
#endif //__CYGWIN__
					case TYMED_ISTREAM:
						{
							STATSTG stat;
							if (S_OK == stm.pstm->Stat(&stat, STATFLAG_NONAME))
								len = (size_t)stat.cbSize.LowPart;
						}
						break;
					//This case is going to be a bitch to implement so it can wait for a while
					//It will need to be a recursive method that stores the STATSTG structures (+ the name), contents/the bytes of data in streams/property sets
					case TYMED_ISTORAGE:
						{
							MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_TYMED_NOTSUP), MB_OK);
						} 
						break; // IStorage*
					case TYMED_GDI:
						{
							len = GetObject(stm.hBitmap, 0, NULL);
							if (len)
							{
								DIBSECTION t;
								GetObject(stm.hBitmap, len, &t);
								len += t.dsBm.bmHeight*t.dsBm.bmWidthBytes*t.dsBm.bmPlanes;
							}
						}
						break; // HBITMAP
					case TYMED_MFPICT:
						{
							len = GlobalSize(stm.hMetaFilePict);
							METAFILEPICT *pMFP = (METAFILEPICT*)GlobalLock(stm.hMetaFilePict);
							if (pMFP)
							{
								len += GetMetaFileBitsEx(pMFP->hMF, 0, NULL);
								GlobalUnlock(stm.hMetaFilePict);
							}
						}
						break; // HMETAFILE
#ifndef __CYGWIN__
					case TYMED_ENHMF:
						{
							len = GetEnhMetaFileHeader(stm.hEnhMetaFile, 0, NULL);
							DWORD n = GetEnhMetaFileDescriptionW(stm.hEnhMetaFile, 0, NULL);
							if (n && n != GDI_ERROR)
								len += sizeof(WCHAR) * n;
							len += GetEnhMetaFileBits(stm.hEnhMetaFile, 0, NULL);
							n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile, 0, NULL);
							if (n && n != GDI_ERROR)
								len += sizeof(LOGPALETTE) + (n - 1) * sizeof(PALETTEENTRY);
						}
						break; // HENHMETAFILE
#endif //__CYGWIN__
					//case TYMED_NULL:break;
				}
				if (!len)
					continue;

				/*Malloc
				We do this so that if the data access fails we only need free(data)
				and don't need to mess around with the m_dataArray.
				Perhaps in the future the m_dataArray can support undoable actions.*/
				BYTE* t = (BYTE*)realloc(data, len);
				if (!t)
					continue;
				data = t;
				memset(data, 0, len);

				//Get data
				switch (stm.tymed)
				{
					case TYMED_HGLOBAL:
						{
							if (LPVOID pmem = GlobalLock(stm.hGlobal))
							{
								memcpy(data, pmem, len);
								gotdata = true;
								GlobalUnlock(stm.hGlobal);
							}
						}
						break;
#ifndef __CYGWIN__
					case TYMED_FILE:
						{
							int fh = _wopen(stm.lpszFileName, _O_BINARY | _O_RDONLY);
							if (fh != -1)
							{
								if (0 < _read(fh, data, len))
									gotdata = true;
								_close(fh);
							}
						}
						break;
#endif //__CYGWIN__
					case TYMED_ISTREAM:
						{
							LARGE_INTEGER zero = { 0 };
							ULARGE_INTEGER pos;
							if (S_OK == stm.pstm->Seek(zero, STREAM_SEEK_CUR, &pos))
							{
								stm.pstm->Seek(zero, STREAM_SEEK_SET, NULL);
								if (S_OK == stm.pstm->Read(data, len, NULL))
									gotdata = true;
								stm.pstm->Seek(*(LARGE_INTEGER*)&pos, STREAM_SEEK_SET, NULL);
							}
						}
						break;
					//This case is going to be a bitch to implement so it can wait for a while
					//It will need to be a recursive method that stores the STATSTG structures (+ the name), contents/the bytes of data in streams/property sets
					case TYMED_ISTORAGE:
						{
							MessageBox(hexwnd.pwnd, GetLangString(IDS_DD_TYMED_NOTSUP), MB_OK);
							goto ERR_ENUM;
						}
						break;//IStorage*
					case TYMED_GDI:
						{
							int l = GetObject(stm.hBitmap, len, data);
							if (l)
							{
								BITMAP* bm = (BITMAP*)data;
								if (bm->bmBits)
									memcpy(&data[l], bm->bmBits, len-l);
								else
									GetBitmapBits(stm.hBitmap, len-l, &data[l]);
								gotdata = true;
							}
						} break; // HBITMAP
					case TYMED_MFPICT:
						{
							if (METAFILEPICT *pMFP = (METAFILEPICT *)GlobalLock(stm.hMetaFilePict))
							{
								memcpy(data, pMFP, sizeof *pMFP);
								GetMetaFileBitsEx(pMFP->hMF, len - sizeof(*pMFP), &data[sizeof(*pMFP)]);
								GlobalUnlock(stm.hMetaFilePict);
								gotdata = true;
							}
						} break;//HMETAFILE
#ifndef __CYGWIN__
					case TYMED_ENHMF:
						{
							DWORD i = 0, n = 0, l = len;
							n = GetEnhMetaFileHeader(stm.hEnhMetaFile, l, (ENHMETAHEADER*)&data[i]);
							l -= n;
							i += n;
							n = GetEnhMetaFileDescriptionW(stm.hEnhMetaFile,
									l / sizeof(WCHAR), (LPWSTR)&data[i]);
							if (n && n != GDI_ERROR)
							{
								n *= sizeof(WCHAR);l -= n; i += n;
							}
							n = GetEnhMetaFileBits(stm.hEnhMetaFile, l, &data[i]);
							l -= n; i += n;
							n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile, 0, NULL);
							if (n && n != GDI_ERROR)
							{
								LOGPALETTE* lp = (LOGPALETTE*)&data[i];
								lp->palVersion = 0x300;
								lp->palNumEntries = (USHORT)n;
								l -= sizeof(lp->palVersion) + sizeof(lp->palNumEntries);
								n = GetEnhMetaFilePaletteEntries(stm.hEnhMetaFile,
										l / sizeof(PALETTEENTRY), &lp->palPalEntry[0]);
								i += n*sizeof(PALETTEENTRY);
							}
							if (i)
								gotdata = true;
						} break; // HENHMETAFILE
#endif //__CYGWIN__
					//case TYMED_NULL:break;
				}

				ReleaseStgMedium(&stm);

				if (gotdata)
				{
					BYTE* DataToInsert = data;
					if (fe.cfFormat == CF_BINARYDATA)
					{
						len = *(DWORD*)data;
						DataToInsert += 4;
					}
					else if (fe.cfFormat == CF_TEXT || fe.cfFormat == CF_OEMTEXT)
					{
						len = strlen((char*)data);
					}
					else if (fe.cfFormat == CF_UNICODETEXT)
					{
						len = sizeof(wchar_t)*wcslen((wchar_t*)data);
					}

					// Insert/overwrite data into m_dataArray
					if (grfKeyState&MK_SHIFT)
					{
						/* Overwite */
						SimpleArray<BYTE> olddata;
						DWORD upper = 1 + hexwnd.m_dataArray.GetUpperBound();
						if (hexwnd.new_pos+len > upper)
						{
							olddata.AppendArray(&hexwnd.m_dataArray[hexwnd.new_pos + (int)totallen], upper - hexwnd.new_pos + (int)totallen);
							/* Need more space */
							if (hexwnd.m_dataArray.SetSize(hexwnd.new_pos + totallen + len))
							{
								hexwnd.m_dataArray.ExpandToSize();
								memcpy(&hexwnd.m_dataArray[hexwnd.new_pos +
										(int)totallen], DataToInsert, len);
								hexwnd.push_undorecord(hexwnd.new_pos + totallen, olddata, olddata.GetLength(), DataToInsert, len);
								gotdata = true;
								totallen += len;
							}
						}
						else
						{
							/* Enough space */
							olddata.AppendArray(&hexwnd.m_dataArray[hexwnd.new_pos + (int)totallen], len);
							memcpy(&hexwnd.m_dataArray[hexwnd.new_pos +
									(int)totallen], DataToInsert, len);
							hexwnd.push_undorecord(hexwnd.new_pos + totallen, olddata, olddata.GetLength(), DataToInsert, len);
							gotdata = true;
							totallen += len;
						}
					}
					else if (hexwnd.m_dataArray.InsertAtGrow(hexwnd.new_pos + totallen, DataToInsert, 0, len))
					{
						/* Insert */
						hexwnd.push_undorecord(hexwnd.new_pos + totallen, NULL, 0, DataToInsert, len);
						gotdata = true;
						totallen += len;
					}
				}
			}

		} // For each selected format

		// Release the data
		free(data);
		data = NULL;
		if (IndexOfDataToInsert < 0)
		{
			free(formats);
			formats = NULL;
		}

		if (gotdata)
		{
			hexwnd.iStartOfSelection = hexwnd.new_pos;
			hexwnd.iEndOfSelection = hexwnd.new_pos + totallen - 1;
			hexwnd.bFilestatusChanged = true;
			hexwnd.bSelected = true;
			hexwnd.resize_window();
			hexwnd.synch_sibling();
		}

		*pdwEffect = copying  ? DROPEFFECT_COPY : DROPEFFECT_MOVE;

		err = S_OK;

ERR_ENUM:
		iefe->Release();
		free(fel);
ERR:
		pDataObject->Release();
		return err;
	}
	pDataObject->Release();

	return S_OK;
}
NS_IMETHODIMP
EditorEventListener::HandleEvent(nsIDOMEvent* aEvent)
{
  NS_ENSURE_TRUE(mEditorBase, NS_ERROR_FAILURE);

  nsCOMPtr<nsIEditor> kungFuDeathGrip = mEditorBase;
  Unused << kungFuDeathGrip; // mEditorBase is not referred to in this function

  WidgetEvent* internalEvent = aEvent->WidgetEventPtr();

  // Let's handle each event with the message of the internal event of the
  // coming event.  If the DOM event was created with improper interface,
  // e.g., keydown event is created with |new MouseEvent("keydown", {});|,
  // its message is always 0.  Therefore, we can ban such strange event easy.
  // However, we need to handle strange "focus" and "blur" event.  See the
  // following code of this switch statement.
  // NOTE: Each event handler may require specific event interface.  Before
  //       calling it, this queries the specific interface.  If it would fail,
  //       each event handler would just ignore the event.  So, in this method,
  //       you don't need to check if the QI succeeded before each call.
  switch (internalEvent->mMessage) {
    // dragenter
    case eDragEnter: {
      nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
      return DragEnter(dragEvent);
    }
    // dragover
    case eDragOver: {
      nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
      return DragOver(dragEvent);
    }
    // dragexit
    case eDragExit: {
      nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
      return DragExit(dragEvent);
    }
    // drop
    case eDrop: {
      nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
      return Drop(dragEvent);
    }
#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
    // keydown
    case eKeyDown: {
      nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
      return KeyDown(keyEvent);
    }
    // keyup
    case eKeyUp: {
      nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
      return KeyUp(keyEvent);
    }
#endif // #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
    // keypress
    case eKeyPress: {
      nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
      return KeyPress(keyEvent);
    }
    // mousedown
    case eMouseDown: {
      nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
      NS_ENSURE_TRUE(mouseEvent, NS_OK);
      // EditorEventListener may receive (1) all mousedown, mouseup and click
      // events, (2) only mousedown event or (3) only mouseup event.
      // mMouseDownOrUpConsumedByIME is used only for ignoring click event if
      // preceding mousedown and/or mouseup event is consumed by IME.
      // Therefore, even if case #2 or case #3 occurs,
      // mMouseDownOrUpConsumedByIME is true here.  Therefore, we should always
      // overwrite it here.
      mMouseDownOrUpConsumedByIME = NotifyIMEOfMouseButtonEvent(mouseEvent);
      return mMouseDownOrUpConsumedByIME ? NS_OK : MouseDown(mouseEvent);
    }
    // mouseup
    case eMouseUp: {
      nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
      NS_ENSURE_TRUE(mouseEvent, NS_OK);
      // See above comment in the eMouseDown case, first.
      // This code assumes that case #1 is occuring.  However, if case #3 may
      // occurs after case #2 and the mousedown is consumed,
      // mMouseDownOrUpConsumedByIME is true even though EditorEventListener
      // has not received the preceding mousedown event of this mouseup event.
      // So, mMouseDownOrUpConsumedByIME may be invalid here.  However,
      // this is not a matter because mMouseDownOrUpConsumedByIME is referred
      // only by eMouseClick case but click event is fired only in case #1.
      // So, before a click event is fired, mMouseDownOrUpConsumedByIME is
      // always initialized in the eMouseDown case if it's referred.
      if (NotifyIMEOfMouseButtonEvent(mouseEvent)) {
        mMouseDownOrUpConsumedByIME = true;
      }
      return mMouseDownOrUpConsumedByIME ? NS_OK : MouseUp(mouseEvent);
    }
    // click
    case eMouseClick: {
      nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aEvent);
      NS_ENSURE_TRUE(mouseEvent, NS_OK);
      // If the preceding mousedown event or mouseup event was consumed,
      // editor shouldn't handle this click event.
      if (mMouseDownOrUpConsumedByIME) {
        mMouseDownOrUpConsumedByIME = false;
        mouseEvent->AsEvent()->PreventDefault();
        return NS_OK;
      }
      return MouseClick(mouseEvent);
    }
    // focus
    case eFocus:
      return Focus(aEvent);
    // blur
    case eBlur:
      return Blur(aEvent);
    // text
    case eCompositionChange:
      return HandleText(aEvent);
    // compositionstart
    case eCompositionStart:
      return HandleStartComposition(aEvent);
    // compositionend
    case eCompositionEnd:
      HandleEndComposition(aEvent);
      return NS_OK;
    default:
      break;
  }

  nsAutoString eventType;
  aEvent->GetType(eventType);
  // We should accept "focus" and "blur" event even if it's synthesized with
  // wrong interface for compatibility with older Gecko.
  if (eventType.EqualsLiteral("focus")) {
    return Focus(aEvent);
  }
  if (eventType.EqualsLiteral("blur")) {
    return Blur(aEvent);
  }
#ifdef DEBUG
  nsPrintfCString assertMessage("Editor doesn't handle \"%s\" event "
    "because its internal event doesn't have proper message",
    NS_ConvertUTF16toUTF8(eventType).get());
  NS_ASSERTION(false, assertMessage.get());
#endif

  return NS_OK;
}