//-------------------------------------------------------------------------------------------
// 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;

}
//------------------------------------------------------------------------------
// 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;
}