⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textviewkeyinput.cpp

📁 支持Unicode及Uniscribe的多语言输入的文本编辑器源码。
💻 CPP
字号:
//
//	MODULE:		TextViewKeyInput.cpp
//
//	PURPOSE:	Keyboard input for TextView
//
//	NOTES:		www.catch22.net
//

#define STRICT
#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <tchar.h>
#include "TextView.h"
#include "TextViewInternal.h"

//
//	TextView::EnterText
//
//	Import the specified text into the TextView at the current
//	cursor position, replacing any text-selection in the process
//
ULONG TextView::EnterText(TCHAR *szText, ULONG nLength)
{
	ULONG selstart = min(m_nSelectionStart, m_nSelectionEnd);
	ULONG selend   = max(m_nSelectionStart, m_nSelectionEnd);

	BOOL  fReplaceSelection = (selstart == selend) ? FALSE : TRUE;
	ULONG erase_len = nLength;

	switch(m_nEditMode)
	{
	case MODE_READONLY:
		return 0;

	case MODE_INSERT:

		// if there is a selection then remove it
		if(fReplaceSelection)
		{
			// group this erase with the insert/replace operation
			m_pTextDoc->m_seq.group();
			m_pTextDoc->erase_text(selstart, selend-selstart);
			m_nCursorOffset = selstart;
		}

		if(!m_pTextDoc->insert_text(m_nCursorOffset, szText, nLength))
			return 0;

		if(fReplaceSelection)
			m_pTextDoc->m_seq.ungroup();
	
		break;

	case MODE_OVERWRITE:

		if(fReplaceSelection)
		{
			erase_len = selend - selstart;
			m_nCursorOffset = selstart;
		}
		else
		{
			ULONG lineoff;
			USPCACHE *uspCache = GetUspCache(0, m_nCurrentLine, &lineoff);

			// single-character overwrite - must behave like 'forward delete'
			// and remove a whole character-cluster (i.e. maybe more than 1 char)
			if(nLength == 1)
			{
				ULONG oldpos = m_nCursorOffset;
				MoveCharNext();
				erase_len = m_nCursorOffset - oldpos;
				m_nCursorOffset = oldpos;
			}

			// if we are at the end of a line (just before the CRLF) then we must
			// not erase any text - instead we act like a regular insertion
			if(m_nCursorOffset == lineoff + uspCache->length_CRLF)
				erase_len = 0;

			
		}

		if(!m_pTextDoc->replace_text(m_nCursorOffset, szText, nLength, erase_len))
			return 0;
		
		break;

	default:
		return 0;
	}

	// update cursor+selection positions
	m_nCursorOffset  += nLength;
	m_nSelectionStart = m_nCursorOffset;
	m_nSelectionEnd   = m_nCursorOffset;

	// we altered the document, recalculate line+scrollbar information
	ResetLineCache();
	RefreshWindow();
	
	Smeg(TRUE);
	NotifyParent(TVN_CURSOR_CHANGE);

	return nLength;
}

BOOL TextView::ForwardDelete()
{
	ULONG selstart = min(m_nSelectionStart, m_nSelectionEnd);
	ULONG selend   = max(m_nSelectionStart, m_nSelectionEnd);

	if(selstart != selend)
	{
		m_pTextDoc->erase_text(selstart, selend-selstart);
		m_nCursorOffset = selstart;

		m_pTextDoc->m_seq.breakopt();
	}
	else
	{
		BYTE tmp[2];
		//USPCACHE		* uspCache;
		//CSCRIPT_LOGATTR * logAttr;
		//ULONG			  lineOffset;
		//ULONG			  index;

		m_pTextDoc->m_seq.render(m_nCursorOffset, tmp, 2);

		/*GetLogAttr(m_nCurrentLine, &uspCache, &logAttr, &lineOffset);
	
		index = m_nCursorOffset - lineOffset;

		do
		{
			m_pTextDoc->seq.erase(m_nCursorOffset, 1);
			index++;
		}
		while(!logAttr[index].fCharStop);*/

		ULONG oldpos = m_nCursorOffset;
		MoveCharNext();

		m_pTextDoc->erase_text(oldpos, m_nCursorOffset - oldpos);
		m_nCursorOffset = oldpos;
		

		//if(tmp[0] == '\r')
		//	m_pTextDoc->erase_text(m_nCursorOffset, 2);
		//else
		//	m_pTextDoc->erase_text(m_nCursorOffset, 1);
	}

	m_nSelectionStart = m_nCursorOffset;
	m_nSelectionEnd   = m_nCursorOffset;

	ResetLineCache();
	RefreshWindow();
	Smeg(FALSE);

	return TRUE;
}

BOOL TextView::BackDelete()
{
	ULONG selstart = min(m_nSelectionStart, m_nSelectionEnd);
	ULONG selend   = max(m_nSelectionStart, m_nSelectionEnd);

	// if there's a selection then delete it
	if(selstart != selend)
	{
		m_pTextDoc->erase_text(selstart, selend-selstart);
		m_nCursorOffset = selstart;
		m_pTextDoc->m_seq.breakopt();
	}
	// otherwise do a back-delete
	else if(m_nCursorOffset > 0)
	{
		//m_nCursorOffset--;
		ULONG oldpos = m_nCursorOffset;
		MoveCharPrev();
		//m_pTextDoc->erase_text(m_nCursorOffset, 1);
		m_pTextDoc->erase_text(m_nCursorOffset, oldpos - m_nCursorOffset);
	}

	m_nSelectionStart = m_nCursorOffset;
	m_nSelectionEnd   = m_nCursorOffset;

	ResetLineCache();
	RefreshWindow();
	Smeg(FALSE);

	return TRUE;
}

void TextView::Smeg(BOOL fAdvancing)
{
	m_pTextDoc->init_linebuffer();

	m_nLineCount   = m_pTextDoc->linecount();

	UpdateMetrics();
	UpdateMarginWidth();
	SetupScrollbars();

	UpdateCaretOffset(m_nCursorOffset, fAdvancing, &m_nCaretPosX, &m_nCurrentLine);
	
	m_nAnchorPosX = m_nCaretPosX;
	ScrollToPosition(m_nCaretPosX, m_nCurrentLine);
	RepositionCaret();
}

BOOL TextView::Undo()
{
	if(m_nEditMode == MODE_READONLY)
		return FALSE;

	if(!m_pTextDoc->Undo(&m_nSelectionStart, &m_nSelectionEnd))
		return FALSE;

	m_nCursorOffset = m_nSelectionEnd;

	ResetLineCache();
	RefreshWindow();

	Smeg(m_nSelectionStart != m_nSelectionEnd);

	return TRUE;
}

BOOL TextView::Redo()
{
	if(m_nEditMode == MODE_READONLY)
		return FALSE;

	if(!m_pTextDoc->Redo(&m_nSelectionStart, &m_nSelectionEnd))
		return FALSE;

	m_nCursorOffset = m_nSelectionEnd;
				
	ResetLineCache();
	RefreshWindow();
	Smeg(m_nSelectionStart != m_nSelectionEnd);

	return TRUE;
}

BOOL TextView::CanUndo()
{
	return m_pTextDoc->m_seq.canundo() ? TRUE : FALSE;
}

BOOL TextView::CanRedo()
{
	return m_pTextDoc->m_seq.canredo() ? TRUE : FALSE;
}

LONG TextView::OnChar(UINT nChar, UINT nFlags)
{
	WCHAR ch = (WCHAR)nChar;

	if(nChar < 32 && nChar != '\t' && nChar != '\r' && nChar != '\n')
		return 0;

	// change CR into a CR/LF sequence
	if(nChar == '\r')
		PostMessage(m_hWnd, WM_CHAR, '\n', 1);

	if(EnterText(&ch, 1))
	{
		if(nChar == '\n')
			m_pTextDoc->m_seq.breakopt();

		NotifyParent(TVN_CHANGED);
	}

	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -