//-------------------------------------------------------------------------------------------
// This public member function opens file with the given name in the Developer Studio
// and highlights the siven line. It also gives focus to the  Developer Studio.
//-------------------------------------------------------------------------------------------
bool CCommands::MakeSelection(CString& file, int line, int col, int len) {
ITextDocument* iDocument;
IDocuments* iDocuments;
ITextSelection* iSelection;

    // First, check if the given file exists. (Developer Studio will hang for a while
    // trying to open non-existing file).
    if(_access(file,04)==-1) return false;


	// Get document collection from the application object.
    if(m_pApplication->get_Documents((IDispatch **)&iDocuments)!=S_OK) 
		return false;

    if(iDocuments==NULL) return false;

	// Open new document and add it to the documents collection (if not exists).
    VARIANT varType;
	varType.vt = VT_BSTR;
	varType.bstrVal=CString("Auto").AllocSysString();

    VARIANT varReadonly;
	varReadonly.vt = VT_BOOL;
	varReadonly.boolVal = FALSE;

    if(iDocuments->Open(file.AllocSysString(),varType,varReadonly,(IDispatch **)&iDocument)!=S_OK) {
		 iDocuments->Release();
		 return false;
	}


	// We do not need documents collection any more
	iDocuments->Release();

    if(iDocument==NULL) return false;

	// Get text selection from the current document
    if(iDocument->get_Selection((IDispatch **)&iSelection)!=S_OK) return false;


	// We do not need document object any more.
	iDocument->Release();

    if(iSelection==NULL) return false;

	// Move to the first position in the given line
    VARIANT selAct;
	selAct.vt = VT_INT;
	selAct.intVal = dsMove;
	iSelection->MoveTo(line,1,selAct);

	VARIANT repCount;
	repCount.vt = VT_INT;
	repCount.intVal = col-1;
	iSelection->CharRight(selAct, repCount);

	// Move to the end of this line in "Shift key pressed" mode.
	selAct.intVal = dsExtend;
	repCount.intVal = len;
	iSelection->CharRight(selAct, repCount);

	// We do not need text selection object any more
	iSelection->Release();


	// Pop-up MSDEV application.
	m_pApplication->put_Active(VARIANT_TRUE);

	return true;

}
bool tomEditCallback::PrepareClipboardData() 
{
    m_text_packer.Clear() ;
    m_html_packer.Clear() ;

    bool res = false ;

    // 获得当前选择图文
    IRichEditOle * edit_ole = m_edit->GetIRichEditOle() ;
    if (edit_ole != NULL)
    {
        ITextDocument * doc = NULL ;//IID_ITextDocument //__uuidof(ITextDocument)
        GUID guid = __uuidof(ITextDocument) ;
        if (S_OK == edit_ole->QueryInterface(__uuidof(ITextDocument), (void**)&doc) && doc != NULL)    // 不知道多判断一个!= NULL是不是脱裤子放屁
        {
            ITextSelection * sel = NULL ;
            if (S_OK == doc->GetSelection(&sel) && sel != NULL)
            {
                //BSTR * sel_text ;
                long sel_start = 0 ;
                sel->GetStart(&sel_start) ;

                BSTR sel_text ;
                if (S_OK == sel->GetText(&sel_text))    // 用完后要负责释放sel_text
                {
                    // 遍历
                    long i ;
                    std::wstring text_temp ;
                    for (i = 0 ; sel_text[i] != 0 ; ++ i)
                    {
                        if (sel_text[i] == WCH_EMBEDDING)
                        {
                            if (!text_temp.empty())
                            {
                                m_text_packer.Append(Clipboard::Ele_Text, text_temp) ;
                                m_html_packer.Append(Clipboard::Ele_Text, text_temp) ;
                                text_temp.clear() ;
                            }

                            // 获得对象
                            REOBJECT ro ;
                            ro.cbStruct = sizeof(ro) ;
                            ro.cp = sel_start + i ;
                            if (S_OK == edit_ole->GetObject(REO_IOB_USE_CP, &ro, REO_GETOBJ_POLEOBJ))
                            {
                                IClipboardDataObject * cdo = NULL ;
                                if (S_OK == ro.poleobj->QueryInterface(IID_IClipboardDataObject, (void**)&cdo))
                                {
                                    std::wstring text_data ;
                                    if (cdo->QueryTextStreamClipboardData(Clipboard::Text, text_data))
                                    {
                                        m_text_packer.Append(Clipboard::Ele_Image, text_data) ;
                                    }
                                    std::wstring html_data ;
                                    if (cdo->QueryTextStreamClipboardData(Clipboard::Html, html_data))
                                    {
                                        m_html_packer.Append(Clipboard::Ele_Image, html_data) ;
                                    }

                                    cdo->Release() ;
                                }

                                ro.poleobj->Release() ;
                            }
                        }
                        else
                        {
                            text_temp.append(1, (wchar_t)(sel_text[i])) ;
                        }
                    }

                    if (!text_temp.empty())
                    {
                        m_text_packer.Append(Clipboard::Ele_Text, text_temp) ;
                        m_html_packer.Append(Clipboard::Ele_Text, text_temp) ;
                        text_temp.clear() ;
                    }

                    SysFreeString(sel_text) ;
                    res = true ;
                }

                sel->Release() ;
            }

            doc->Release() ;
        }
    }

    return res ;
}
//------------------------------------------------------------------------------
// This function fills file name, line number and ending column number
// for the selected token as well as a token itself.
//------------------------------------------------------------------------------
bool CCommands::getSelection(CComBSTR& file, CComBSTR& token, long& offset, long& line, long& column) {
ITextDocument* iDocument;
ITextSelection* iSelection;

	// Getting the currently opened document object.

	if(m_pApplication->get_ActiveDocument((IDispatch **)&iDocument)!=S_OK) 
		return false;
	if(iDocument==NULL) return false;

	// Reading the file name
	BSTR bstrName;
	iDocument->get_FullName(&bstrName);
	file=bstrName;

	// Getting text selection object from the active document
	if(iDocument->get_Selection((IDispatch **)&iSelection)!=S_OK) 
		return false;

	// We do not need active document object any more.
	iDocument->Release();

	if(iSelection==NULL) return false;

	// Reading currently selected token
	BSTR bstrToken;
	if(iSelection->get_Text(&bstrToken)!=S_OK) 
		return false;
	token = bstrToken;

	long size = token.Length();
	if(iSelection->get_TopLine(&line)!=S_OK)     return false;
	if(iSelection->get_CurrentColumn(&column)!=S_OK) return false;

	VARIANT selMove;
	selMove.vt = VT_INT;
	selMove.intVal = dsMove;
	VARIANT selExtend;
	selExtend.vt = VT_INT;
	selExtend.intVal = dsExtend;
	VARIANT repCount;
	repCount.vt = VT_INT;
	repCount.intVal = 1;

	// To determine which end of the selection the cursor is at,
	// we extend the selection one character left from the cursor 
	// and see whether the selection has gotten longer or shorter.

	bool cursor_at_right_end = true;

	if (column <= 1)
	{
		cursor_at_right_end = false;
	}
	else
	{
		long newsize;
		iSelection->CharLeft(selExtend, repCount);

		if(iSelection->get_Text(&bstrToken)==S_OK) 
		{
			CComBSTR newToken = bstrToken;
			newsize = newToken.Length();
			if (newsize > size)
			{
				// If extending left increases the size, the
				// cursor must be at the left end.
				cursor_at_right_end = false;
			}
		}
		iSelection->CharRight(selExtend, repCount);
	}

	// Calculating column in file characters, not in screen
	// position (detecting tabs)
	long lineOffset = 0;
	long tempColumn = column;
	while (tempColumn > 1) {
		iSelection->CharLeft(selMove, repCount);
		iSelection->get_CurrentColumn(&tempColumn);
		lineOffset++;
	}

	// Restoring selection after calculation:
	// First, go to the end without the cursor
	if (cursor_at_right_end)
	{
		iSelection->MoveTo(line, column-size, selMove);
	}
	else // Cursor at left end of selection
	{
		iSelection->MoveTo(line, column+size, selMove);
	}
	// Now make the selection
	iSelection->MoveTo(line, column, selExtend);

	iSelection->Release();
	column = lineOffset;
	if(size!=0)
		column--;

	offset = -1; // can not determine the offset
	return true;
}