Пример #1
0
char* trimright( char* string )
{
	char *lpsz = string+strlen(string);

	lpsz = _tcsdec(string, lpsz);
	
	while( lpsz && _istspace(*lpsz) )
		lpsz = _tcsdec(string, lpsz);

	if( lpsz==NULL )lpsz=string;
	else lpsz++;

	*lpsz = '\0';

	return string;
}
Пример #2
0
inline TCHAR CFilePath::GetLastChar(CString const &sString)
{
    LPCTSTR psTemp = sString;
    LPCTSTR psLastChar = _tcsdec(psTemp, psTemp + sString.GetLength());
    if (psLastChar == NULL)
        return 0;
    else
        return *psLastChar;
}
Пример #3
0
INT64 GetFolderSize(LPCTSTR szFolder, BOOL bIncludeChild, FolderFilter fn)
{
	WIN32_FIND_DATA FindFileData;
	HANDLE hFind = INVALID_HANDLE_VALUE;

	CString strFolder(szFolder);
	strFolder.Append( _T("\\*") );

	INT64 folderSize = 0;
	hFind = FindFirstFile(strFolder, &FindFileData);
	if (hFind != INVALID_HANDLE_VALUE) 
	{
		printf ("First file name is %s\n", FindFileData.cFileName);
		do 
		{
			printf ("Next file name is %s\n", FindFileData.cFileName);

			if( _tcsicmp(_T("."), FindFileData.cFileName)==0 
				|| _tcsicmp(_T(".."), FindFileData.cFileName)==0 )
			{
				continue;
			}
			if( FindFileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
			{
				if( bIncludeChild )
				{
					CString strResult = szFolder;
					LPCTSTR pszResult;
					LPCTSTR pchLast;
					pszResult = strResult;
					pchLast = _tcsdec( pszResult, pszResult+strResult.GetLength() );
					ATLASSERT(pchLast!=NULL);
					if ((*pchLast != _T('\\')) && (*pchLast != _T('/')))
						strResult += _T('\\');
					strResult += FindFileData.cFileName;
					folderSize += GetFolderSize( strResult, bIncludeChild );
				}
			}
			else
			{
				if( !fn || fn(szFolder, FindFileData.cFileName) )
				{
					ULARGE_INTEGER nFileSize;
					nFileSize.LowPart = FindFileData.nFileSizeLow;
					nFileSize.HighPart = FindFileData.nFileSizeHigh;
					folderSize += nFileSize.QuadPart;
				}
			}

		} while (FindNextFile(hFind, &FindFileData) != 0);
		FindClose(hFind);
	}
	return folderSize;
}
Пример #4
0
CString CFileFindWDS::altGetFilePath( ) const {
	ASSERT( m_hContext != NULL );
	ASSERT_VALID( this );

	CString strResult = m_strRoot;
	PCTSTR pszResult = m_strRoot;
	//_tcsdec: "Moves a string pointer back one character"
	PCTSTR pchLast = _tcsdec( pszResult, pszResult + m_strRoot.GetLength( ) );
	ENSURE( pchLast != NULL );
	if ( ( *pchLast != _T( '\\' ) ) && ( *pchLast != _T( '/' ) ) ) {
		strResult += '\\';
		}
	auto fName = altGetFileName( );
	if ( fName != NULL ) {
		strResult += fName;
		}
	return strResult;
	}
Пример #5
0
static UINT AFXAPI
ClipLine(CDC* pDC, int aCharWidths[256], int cxLine, int nTabStop,
	LPCTSTR lpszText, UINT nIndex, UINT nIndexEnd)
{
	ASSERT_VALID(pDC);
	ASSERT(nIndex < nIndexEnd);
	ASSERT(AfxIsValidAddress(lpszText, nIndexEnd, FALSE));
	UNUSED_ALWAYS(nTabStop);    // unused in Mac build

	TEXTMETRIC tm;
	::GetTextMetrics(pDC->m_hDC, &tm);

	// make an initial guess on the number of characters that will fit
	int cx = 0;
	LPCTSTR lpszStart = lpszText + nIndex;
	LPCTSTR lpszStop = lpszText + nIndexEnd;
	LPCTSTR lpsz = lpszStart;
	while (lpsz < lpszStop)
	{
#ifndef _MAC
		if (*lpsz == '\t')
			cx += nTabStop - (cx % nTabStop);
		else
#endif
		{
#ifdef _UNICODE
			if (*lpsz <= 0xFF)
				cx += aCharWidths[(BYTE)*lpsz];
			else
				cx += tm.tmAveCharWidth;
#else //_UNICODE
			if (_afxDBCS && _istlead(*lpsz))
			{
				++lpsz;
				cx += tm.tmAveCharWidth;
			}
			else
				cx += aCharWidths[(BYTE)*lpsz];
#endif //!_UNICODE
		}
		++lpsz;
		if (cx > cxLine)
			break;
	}

	// adjust for errors in the guess
#ifndef _MAC
	cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
#else
	cx = pDC->GetTextExtent(lpszStart, lpsz-lpszStart).cx;
#endif
	if (cx > cxLine)
	{
		// remove characters until it fits
		do
		{
			ASSERT(lpsz != lpszStart);
			if (_afxDBCS)
				lpsz = _tcsdec(lpszStart, lpsz);
			else
				--lpsz;
#ifndef _MAC
			cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
#else
			cx = pDC->GetTextExtent(lpszStart, lpsz-lpszStart).cx;
#endif
		} while (cx > cxLine);
	}
	else if (cx < cxLine)
	{
		// add characters until it doesn't fit
		while (lpsz < lpszStop)
		{
			lpsz = _tcsinc(lpsz);
			ASSERT(lpsz <= lpszStop);
#ifndef _MAC
			cx = pDC->GetTabbedTextExtent(lpszStart, lpsz-lpszStart, 1, &nTabStop).cx;
#else
			cx = pDC->GetTextExtent(lpszStart, lpsz-lpszStart).cx;
#endif
			if (cx > cxLine)
			{
				if (_afxDBCS)
					lpsz = _tcsdec(lpszStart, lpsz);
				else
					--lpsz;
				break;
			}
		}
	}

	// return index of character just past the last that would fit
	return lpsz - lpszText;
}
Пример #6
0
BOOL CEditView::FindText(LPCTSTR lpszFind, BOOL bNext, BOOL bCase)
{
	ASSERT_VALID(this);
	ASSERT(lpszFind != NULL);
	ASSERT(*lpszFind != '\0');

	UINT nLen = GetBufferLength();
	int nStartChar, nEndChar;
	GetEditCtrl().GetSel(nStartChar, nEndChar);
	UINT nStart = nStartChar;
	int iDir = bNext ? +1 : -1;

	// can't find a match before the first character
	if (nStart == 0 && iDir < 0)
		return FALSE;

	CWaitCursor wait;
	LPCTSTR lpszText = LockBuffer();

	if (iDir < 0)
	{
		// always go back one for search backwards
		nStart -= (lpszText+nStart) -
			_tcsdec(lpszText, lpszText+nStart);
	}
	else if (nStartChar != nEndChar && SameAsSelected(lpszFind, bCase))
	{
		// easy to go backward/forward with SBCS
		if (_istlead(lpszText[nStart]))
			nStart++;
		nStart += iDir;
	}

	// handle search with nStart past end of buffer
	size_t nLenFind = lstrlen(lpszFind);
	if (nStart+nLenFind-1 >= nLen)
	{
		if (iDir < 0 && nLen >= nLenFind)
		{
			if (_afxDBCS)
			{
				// walk back to previous character n times
				nStart = nLen;
				int n = nLenFind;
				while (n--)
				{
					nStart -= (lpszText+nStart) -
						_tcsdec(lpszText, lpszText+nStart);
				}
			}
			else
			{
				// single-byte character set is easy and fast
				nStart = nLen - nLenFind;
			}
			ASSERT(nStart+nLenFind-1 <= nLen);
		}
		else
		{
			UnlockBuffer();
			return FALSE;
		}
	}

	// start the search at nStart
	LPCTSTR lpsz = lpszText + nStart;
	AFX_COMPARE_PROC pfnCompare = bCase ? lstrcmp : lstrcmpi;

	if (_afxDBCS)
	{
		// double-byte string search
		LPCTSTR lpszStop;
		if (iDir > 0)
		{
			// start at current and find _first_ occurrance
			lpszStop = lpszText + nLen - nLenFind + 1;
		}
		else
		{
			// start at top and find _last_ occurrance
			lpszStop = lpsz;
			lpsz = lpszText;
		}

		LPCTSTR lpszFound = NULL;
		while (lpsz <= lpszStop)
		{
			if (!bCase || (*lpsz == *lpszFind &&
				(!_istlead(*lpsz) || lpsz[1] == lpszFind[1])))
			{
				LPTSTR lpch = (LPTSTR)(lpsz + nLenFind);
				TCHAR chSave = *lpch;
				*lpch = '\0';
				int nResult = (*pfnCompare)(lpsz, lpszFind);
				*lpch = chSave;
				if (nResult == 0)
				{
					lpszFound = lpsz;
					if (iDir > 0)
						break;
				}
			}
			lpsz = _tcsinc(lpsz);
		}
		UnlockBuffer();

		if (lpszFound != NULL)
		{
			int n = (int)(lpszFound - lpszText);
			GetEditCtrl().SetSel(n, n+nLenFind);
			return TRUE;
		}
	}
	else
	{
		// single-byte string search
		UINT nCompare;
		if (iDir < 0)
			nCompare = (UINT)(lpsz - lpszText) + 1;
		else
			nCompare = nLen - (UINT)(lpsz - lpszText) - nLenFind + 1;

		while (nCompare > 0)
		{
			ASSERT(lpsz >= lpszText);
			ASSERT(lpsz+nLenFind-1 <= lpszText+nLen-1);

			LPSTR lpch = (LPSTR)(lpsz + nLenFind);
			char chSave = *lpch;
			*lpch = '\0';
			int nResult = (*pfnCompare)(lpsz, lpszFind);
			*lpch = chSave;
			if (nResult == 0)
			{
				UnlockBuffer();
				int n = (int)(lpsz - lpszText);
				GetEditCtrl().SetSel(n, n+nLenFind);
				ASSERT_VALID(this);
				return TRUE;
			}

			// restore character at end of search
			*lpch = chSave;

			// move on to next substring
			nCompare--;
			lpsz += iDir;
		}
		UnlockBuffer();
	}

	ASSERT_VALID(this);
	return FALSE;
}
Пример #7
0
//
// Find text in the edit control:
LONG FIND_EditText (WPARAM wParam, LPARAM lParam)
{
    CaFindInformation* pFindInfo = (CaFindInformation*)lParam;
    ASSERT (pFindInfo);
    if (!pFindInfo)
        return 0L;

    CEdit* pCtrl = (CEdit*)wParam;
    ASSERT (pCtrl);
    if (!pCtrl)
        return 0L;

    if (pFindInfo->GetEditWindow() != pCtrl || pFindInfo->GetEditWindow() == NULL)
    {
        pFindInfo->SetEditWindow(pCtrl);
        pFindInfo->SetEditPos (0);
    }

    CString strBuffer;
    pCtrl->GetWindowText(strBuffer);
    CString strWhat = pFindInfo->GetWhat();
    int nLength = strBuffer.GetLength();

    if (!(pFindInfo->GetFlag() & FR_MATCHCASE))
    {
        strBuffer.MakeUpper();
        strWhat.MakeUpper();
    }

    int nStartFind = pFindInfo->GetEditPos ();
    int nFound = -1;

    if (!(pFindInfo->GetFlag() & FR_WHOLEWORD))
    {
        nFound = strBuffer.Find (strWhat, nStartFind);
        if (nFound != -1)
        {
            pFindInfo->SetEditPos (nFound+strWhat.GetLength());
            pCtrl->SetSel (nFound, nFound+strWhat.GetLength());

            return FIND_RESULT_OK;
        }
    }
    else
    {
        CString strSeparators = theApp.m_strWordSeparator; // Seperator of whole word.
        nFound = strBuffer.Find (strWhat, nStartFind);

        while (nFound != -1)
        {
            if (nFound > 0)
            {
                //
                // Check if there is a separator:
                TCHAR* pPrev =  (TCHAR* )(LPCTSTR)strBuffer +nFound;
                pPrev = _tcsdec((const TCHAR* )strBuffer, pPrev);
                TCHAR tchSep1 = pPrev? *pPrev: _T('\0'); //strBuffer.GetAt (nFound -1);
                TCHAR tchSep2 = strBuffer.GetAt (nFound + strWhat.GetLength());
                if (strSeparators.Find(tchSep1) != -1 && strSeparators.Find(tchSep2) != -1)
                {
                    pFindInfo->SetEditPos (nFound+strWhat.GetLength());
                    pCtrl->SetSel (nFound, nFound+strWhat.GetLength());

                    return FIND_RESULT_OK;
                }
                else
                {
                    nStartFind = nFound+strWhat.GetLength();
                    nFound = strBuffer.Find (strWhat, nStartFind);
                }
            }
        }
    }

    pFindInfo->SetEditPos (nLength);
    if (nLength > 0 && nStartFind > 0)
        return FIND_RESULT_END;

    return FIND_RESULT_NOTFOUND;
}
Пример #8
0
UCHAR
processIncludeFile(
    char *s
    )
{
    MACRODEF *m;
    struct _finddata_t finddata;
    NMHANDLE searchHandle;
    char *t, *p, *u;
    int c = 0;
    int i;

    if (!*s || *s == '#') {
        makeError(line, SYNTAX_NO_NAME);
    }

    if ((t = _tcspbrk(s,"\t#"))) {
        if (*t == '#') {
            c = *t;
        }

        *t = '\0';

        if (!c) {
            for (u = t; *++u;) {        // check for extra
                if (*u == '#') {
                    break;              // text on line
                }

                if (!WHITESPACE(*u)) {
                    makeError(line, SYNTAX_UNEXPECTED_TOKEN, u);
                }
            }
        }
    } else {
        t = s + _tcslen(s);
    }

	// remove trailing white space
	while (t > s) {
		char *prev;
		prev = _tcsdec(s, t);
		if (!WHITESPACE(*prev))
			break;
		t = prev;
	}
	*t = '\0';

    if (*s == '<' && *(t-1) == '>') {
        char *pt;

        *--t = '\0';
        p = removeMacros(++s);
        p = p == s ? makeString(s) : p;
        t = (m = findMacro("INCLUDE")) ? m->values->text : (char*) NULL;
        if (t != NULL) {        // expand INCLUDE macro before passing it on
            char * pt1;

            pt1= makeString(t);
            pt = removeMacros(pt1);
            if (pt != pt1) {
                FREE(pt1);             // we've got a new string, free old one
            }
        } else {
            pt = NULL;
        }

        if (!(u = searchPath(pt, p, &finddata, &searchHandle))) {
            makeError(line, CANT_OPEN_FILE, p);
        }

        if (pt) {
            FREE(pt);
        }

        FREE(p);
        s = u;
    } else {
        if (*s == '"' && *(t-1) == '"') {
            *--t = '\0';
            ++s;
        }
        p = removeMacros(s);
        p = p == s ? makeString(s) : p;
        if (!findFirst(p, &finddata, &searchHandle)) {
            if (!_tcspbrk(p, "\\/:")) {
                //use C sematics for include
                for (i = incTop;i >= 0;i--) {
                    t = (i == incTop) ? fName : incStack[i].name;
                    if (!(t = getPath(t)))
                        continue;
                    u = (char *)allocate(_tcslen(t) + 1 + _tcslen(p) + 1);
                    _tcscat(_tcscat(_tcscpy(u, t), PATH_SEPARATOR), p);
                    if (findFirst(u, &finddata, &searchHandle)) {
                        s = u;
                        FREE(t);
                        break;
                    }
                    FREE(t);
                    FREE(u);
                }
                FREE(p);
                if (i < 0) {
                    makeError(line, CANT_OPEN_FILE, s);
                }
            } else {
                makeError(line, CANT_OPEN_FILE, p);
            }
        }
    }

    for (i = 0; i < incTop; ++i) {      // test for cycles
        if (!_tcsicmp(s,incStack[i].name)) {
            makeError(line, CYCLE_IN_INCLUDES, s);
        }
    }

    incStack[incTop].file = file;       // push info on stack
    incStack[incTop].line = line;
    incStack[incTop++].name = fName;
    currentLine = 0;

    if (!(file = OpenValidateMakefile(s,"rt"))) {   // read, text mode
        makeError(line,CANT_OPEN_FILE,s);
    }

    fName = makeString(s);
    line = 1;
    colZero = TRUE;                     // parser needs to see some kind of
    c = lgetc();                        //  newline to initialize it for this

    if ((colZero = (BOOL) !WHITESPACE(c))) {  // file
        UngetTxtChr(c,file);
        line=0;                         // We did not start reading the file
        return(NEWLINE);
    }

    return(NEWLINESPACE);
}
Пример #9
0
void CSelection::Extend( Direction eDirection, Amount eAmount, BOOL bScrollIfNeccessary, BOOL bDamage, BOOL bAllowPastEndOfLine )
{
    CBuffer *pBuffer = m_pCtrl->GetBuffer();
    int nLineCount = pBuffer->GetLineCount();
    BOOL bEnforceSelBounds = BoundSelection();
    int nSaveEndRow = m_nEndRow;
    int nSaveEndCol = m_nEndCol;
    BOOL bUsePreferredCol = FALSE;

    if ( nLineCount )
    {
        int nOldEndRow = m_nEndRow;
        int nOldStartRow = m_nStartRow;
        LPCTSTR pszEndLineStart = pBuffer->GetLineText( m_nEndRow );
        int nEndLineLen = pBuffer->GetLineLength( m_nEndRow );

        BOOL bStartRowChanged = FALSE;

        switch ( eDirection )
        {
        case eUp:
        {
            switch ( eAmount )
            {
            case eChar:
            {
                m_nEndRow--;
                bUsePreferredCol = TRUE;
                break;
            }
            case ePage:
            {
                m_nEndRow -= ( m_pView->GetBottomIndex( FALSE ) - m_pView->GetTopIndex() );
                break;
            }
            case eSmartAll:
            case eAll:
            {
                m_nEndRow = 0;
                break;
            }
            }
            break;
        }
        case eDown:
        {
            switch ( eAmount )
            {
            case eChar:
            {
                m_nEndRow++;
                bUsePreferredCol = TRUE;
                break;
            }
            case ePage:
            {
                int nTemp = m_nEndRow + ( m_pView->GetBottomIndex( FALSE ) - m_pView->GetTopIndex() );
                m_nEndRow = min( nLineCount, nTemp );
                break;
            }
            case eAll:
            case eSmartAll:
            {
                m_nEndRow = nLineCount - 1;
                break;
            }
            }
            break;
        }
        case eLeft:
        {
            switch ( eAmount )
            {
            case eChar:
            {
                if ( m_nEndCol == 0 || m_nEndCol > nEndLineLen )
                    m_nEndCol--;
                else
                    m_nEndCol -= _tclen_prev( pszEndLineStart, pszEndLineStart + m_nEndCol );
                if ( m_nEndCol < 0 )
                {
                    if ( bAllowPastEndOfLine && m_nEndRow > 0 )
                    {
                        m_nEndRow--;
                        m_nEndCol = pBuffer->GetLineLength( m_nEndRow );
                        bEnforceSelBounds = FALSE;	// already enforced by previous statement!
                    }
                    else
                    {
                        m_nEndCol = 0;
                    }
                }
                break;
            }
            case ePage:
            {
                m_nEndCol -= ( m_pView->GetRightIndex( FALSE ) - m_pView->GetLeftIndex() );
                break;
            }
            case eAll:
            {
                m_nEndCol = 0;
                break;
            }
            case eSmartAll:
            {
                LPCTSTR pszLine = pBuffer->GetLineText( m_nEndRow );
                int nFirstNonSpace = 0;
                while ( *pszLine && ( *pszLine == _T(' ') || *pszLine == _T('\t') ) )
                {
                    nFirstNonSpace++;
                    pszLine = _tcsinc( pszLine );
                }

                // jump between absolute left and 'textual' left
                m_nEndCol = ( m_nEndCol == nFirstNonSpace ? 0 : nFirstNonSpace );
                break;
            }
            case eWord:
            {
                pBuffer->AdvanceToWordStart( m_nEndRow, m_nEndCol, FALSE, TRUE );
                break;
            }
            case eWordEnd:
            {
                pBuffer->AdvanceToWordEnd( m_nEndRow, m_nEndCol, FALSE, TRUE );
                break;
            }
            case eSentence:
            {
                pBuffer->AdvanceToSentenceStart( m_nEndRow, m_nEndCol, FALSE );
                break;
            }
            }
            break;
        }
        case eRight:
        {
            switch ( eAmount )
            {
            case eChar:
            {
                if ( m_nEndCol >= nEndLineLen )
                    m_nEndCol++;
                else
                    m_nEndCol += _tclen( pszEndLineStart + m_nEndCol );
                break;
            }
            case ePage:
            {
                m_nEndCol += ( m_pView->GetRightIndex( FALSE ) - m_pView->GetLeftIndex() );
                break;
            }
            case eAll:
            {
                m_nEndCol = pBuffer->GetLineLength( m_nEndRow );
                break;
            }
            case eSmartAll:
            {
                LPCTSTR pszStart = pBuffer->GetLineText( m_nEndRow );
                int nLastChar = pBuffer->GetLineLength( m_nEndRow );
                int nFirstNonSpace = nLastChar;
                LPCTSTR pszEnd = pszStart + nFirstNonSpace - 1;
                while ( ( pszEnd >= pszStart ) && ( *pszEnd == _T(' ') || *pszEnd == _T('\t') ) )
                {
                    nFirstNonSpace--;
                    pszEnd = _tcsdec( pszStart, pszEnd );
                }

                // jump between absolute right and 'textual' right
                m_nEndCol = ( m_nEndCol <= nFirstNonSpace ? nLastChar : nFirstNonSpace );
                break;
            }
            case eWord:
            {
                pBuffer->AdvanceToWordStart( m_nEndRow, m_nEndCol, TRUE, TRUE );
                break;
            }
            case eWordEnd:
            {
                pBuffer->AdvanceToWordEnd( m_nEndRow, m_nEndCol, TRUE, TRUE );
                break;
            }
            case eSentence:
            {
                pBuffer->AdvanceToSentenceStart( m_nEndRow, m_nEndCol, TRUE );
                break;
            }
            }
            break;
        }
        case eOutward:
        {
            switch ( eAmount )
            {
            case eWord:
            {
                m_nStartCol = m_nEndCol;
                int nLineLen = pBuffer->GetLineLength( m_nEndRow );
                if ( m_nStartCol <= nLineLen )
                {
                    if ( m_nStartCol )
                    {
                        pBuffer->AdvanceToWordStart( m_nEndRow, m_nStartCol, FALSE, FALSE );
                    }
                    m_nEndCol = m_nStartCol;
                    if ( m_nStartCol < nLineLen )
                    {
                        pBuffer->AdvanceToWordEnd( m_nEndRow, m_nEndCol, TRUE, FALSE );
                    }
                }
                break;
            }
            case eSentence:
            {
                m_nStartRow = m_nEndRow;
                m_nStartCol = 0;
                pBuffer->AdvanceToSentenceStart( m_nStartRow, m_nStartCol, FALSE );
                m_nEndCol = m_nStartCol;
                m_nEndRow = m_nStartRow;
                pBuffer->AdvanceToSentenceStart( m_nEndRow, m_nEndCol, TRUE );
                bStartRowChanged = ( m_nStartRow != nOldStartRow );
                break;
            }
            }
            break;
        }
        }

        int nTemp = nLineCount - 1;
        m_nEndRow = min( m_nEndRow, nTemp );
        m_nEndRow = max( 0, m_nEndRow );

        m_nEndCol = ( nLineCount == 0 ) ? 0 : max( 0, m_nEndCol );
        BOOL bEndViewColUpToDate = FALSE;

        // keep cursor within the line's bounds if requested to
        if ( bEnforceSelBounds )
        {
            // special case: if moving left one char and beyond the end of the line,
            // do the fixup now or else the one-char move will be nullified by
            // EnforceSelBounds()
            if ( nLineCount && eDirection == eLeft && eAmount == eChar )
            {
                int nEndRowLen = pBuffer->GetLineLength( m_nEndRow );
                if ( m_nEndCol >= nEndRowLen )
                {
                    m_nEndCol = nEndRowLen - 1;
                    m_nEndCol = max( 0, m_nEndCol );
                }
            }

            if ( bUsePreferredCol && nSaveEndRow != m_nEndRow )
            {
                m_nEndCol = pBuffer->ConvertViewColToBufferCol( m_nEndRow, m_nEndViewColPreferred );
            }

            BOOL bFixup = EnforceSelBounds();

            // if we didn't have to fix-up the selection, remember this new col position
            // as the preferred position.
            if ( !bFixup )
            {
                if ( bUsePreferredCol && nSaveEndRow != m_nEndRow )
                {
                    // moved vertically -- need to translate view col from one row to another
                    int nBuffCol = pBuffer->ConvertViewColToBufferCol( m_nEndRow, m_nEndViewColPreferred );
                    m_nEndViewCol = pBuffer->ConvertBufferColToViewCol( m_nEndRow, nBuffCol );
                    m_nEndCol = pBuffer->ConvertViewColToBufferCol( m_nEndRow, m_nEndViewCol );
                }
                else if ( nSaveEndCol != m_nEndCol )
                {
                    m_nEndViewCol = pBuffer->ConvertBufferColToViewCol( m_nEndRow, m_nEndCol );
                    m_nEndViewColPreferred = m_nEndViewCol;
                }
                bEndViewColUpToDate = TRUE;
            }
        }

        // since m_nEndCol may have changed, we need to recalc the view position and re-snap m_nEndCol to the current row
        if ( !bEndViewColUpToDate )
        {
            m_nEndViewCol = pBuffer->ConvertBufferColToViewCol( m_nEndRow, m_nEndCol );
            m_nEndCol = pBuffer->ConvertViewColToBufferCol( m_nEndRow, m_nEndViewCol );
        }

        if ( eDirection == eOutward )
        {
            m_nStartViewCol = pBuffer->ConvertBufferColToViewCol( m_nStartRow, m_nStartCol );
        }

        if ( bDamage )
        {
            int nDamageStart = min( nOldEndRow, m_nEndRow );
            int nDamageEnd = max( nOldEndRow, m_nEndRow );
            if ( m_bColumnSel )
            {
                nDamageStart = min( nDamageStart, nOldStartRow );
                nDamageStart = min( nDamageStart, m_nStartRow );
                nDamageEnd = max( nDamageEnd, nOldStartRow );
                nDamageEnd = max( nDamageEnd, m_nStartRow );
            }
            if ( bStartRowChanged )
            {
                nDamageStart = min( nDamageStart, nOldStartRow );
                nDamageStart = min( nDamageStart, m_nStartRow );
                nDamageEnd = max( nDamageEnd, nOldEndRow );
                nDamageEnd = max( nDamageEnd, m_nEndRow );
            }

            m_pView->DamageView( nDamageStart, nDamageEnd );
        }

        // if user changed lines, notify the control so it can normalize the text case in the
        // line that was just left.
        if ( eDirection == eUp || eDirection == eDown )
        {
            m_pCtrl->OnChangeLineSelection();
        }
    }
    else
    {
        m_nEndCol = m_nEndRow = m_nEndViewCol = m_nStartViewCol = m_nStartCol = m_nStartRow = 0;
    }
    if ( bScrollIfNeccessary )
    {
        EnsureVisible( TRUE );
    }
}