📄 console.cpp
字号:
/* $Id: Console.cpp 12803 2005-01-04 21:40:25Z narnaoud $
*
* regexpl - Console Registry Explorer
*
* Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
// Console.cpp: implementation of the CConsole class.
//
//////////////////////////////////////////////////////////////////////
#include "ph.h"
#include "Console.h"
#define TAB_WIDTH 8
#define MORE_STRING _T("-- Press space to view more. Press q or Ctrl+break to cancel.--")
#define MORE_EMPTY_STRING _T(" ")
/*
TCHAR * _tcsnchr(const TCHAR *string, TCHAR ch, int count)
{
while (count--)
{
if (*string == 0) return NULL;
if (*string == ch) return const_cast <char *>(string);
string++;
}
return NULL;
}*/
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CConsole::CConsole()
{
m_hStdIn = INVALID_HANDLE_VALUE;
m_hStdOut = INVALID_HANDLE_VALUE;
m_blnInsetMode = TRUE; // Insert
// m_blnInsetMode = FALSE; // Overwrite
m_dwInsertModeCursorHeight = 15;
m_dwOverwriteModeCursorHeight = 100;
// m_Lines = 0;
m_pchBuffer = NULL;
m_pchBuffer1 = NULL;
m_pchBuffer2 = NULL;
m_pfReplaceCompletionCallback = NULL;
m_blnMoreMode = TRUE;
m_dwOldInputMode = 0;
m_dwOldOutputMode = 0;
m_blnOldInputModeSaved = FALSE;
m_blnOldOutputModeSaved = FALSE;
}
CConsole::~CConsole()
{
if (m_pchBuffer)
delete m_pchBuffer;
if (m_pchBuffer1)
delete m_pchBuffer1;
if (m_pchBuffer2)
delete m_pchBuffer2;
if (m_blnOldInputModeSaved)
SetConsoleMode(m_hStdIn,m_dwOldInputMode);
if (m_blnOldOutputModeSaved)
SetConsoleMode(m_hStdOut,m_dwOldOutputMode);
if (m_hStdIn != INVALID_HANDLE_VALUE)
VERIFY(CloseHandle(m_hStdIn));
if (m_hStdOut != INVALID_HANDLE_VALUE)
VERIFY(CloseHandle(m_hStdOut));
}
BOOL CConsole::Write(const TCHAR *p, DWORD dwChars)
{
if (m_hStdOut == INVALID_HANDLE_VALUE)
return FALSE;
if (m_hStdIn == INVALID_HANDLE_VALUE)
return FALSE;
if (p == NULL)
{
ASSERT(FALSE);
return FALSE;
}
DWORD dwCharsToWrite = (dwChars)?dwChars:_tcslen(p);
DWORD dwCharsWrittenAdd = 0;
BOOL ret = TRUE;
while (dwCharsToWrite && (!m_blnDisableWrite))
{
switch(p[dwCharsWrittenAdd])
{
case _T('\n'):
m_CursorPosition.Y++;
m_CursorPosition.X = 0;
break;
case _T('\r'):
dwCharsWrittenAdd++;
dwCharsToWrite--;
continue;
case _T('\t'):
do
{
if (!Write(_T(" "))) return FALSE;
}
while ((m_CursorPosition.X % TAB_WIDTH) && (!m_blnDisableWrite));
dwCharsWrittenAdd++;
dwCharsToWrite--;
continue;
default:
{
if (!WriteChar(p[dwCharsWrittenAdd])) return FALSE;
m_CursorPosition.X++;
}
}
if (m_CursorPosition.X == m_BufferSize.X)
{
m_CursorPosition.Y++;
m_CursorPosition.X = 0;
}
if (m_CursorPosition.Y == m_BufferSize.Y)
{
ASSERT(m_CursorPosition.X == 0);
SMALL_RECT Src;
Src.Left = 0;
Src.Right = (SHORT)(m_BufferSize.X-1);
Src.Top = 1;
Src.Bottom = (SHORT)(m_BufferSize.Y-1);
CHAR_INFO ci;
#ifdef UNICODE
ci.Char.UnicodeChar = L' ';
#else
ci.Char.AsciiChar = ' ';
#endif
ci.Attributes = 0;
COORD Dest;
Dest.X = 0;
Dest.Y = 0;
if (!ScrollConsoleScreenBuffer(m_hStdOut,&Src,NULL,Dest,&ci)) return FALSE;
m_CursorPosition.Y--;
m_LinesScrolled++;
}
if (!SetConsoleCursorPosition(m_hStdOut,m_CursorPosition)) return FALSE;
VERIFY(WriteChar(_T(' ')));
if ((m_blnMoreMode)&&(m_CursorPosition.X == 0))
{
m_Lines++;
if (m_Lines >= m_BufferSize.Y-1)
{
ASSERT(m_Lines == m_BufferSize.Y-1);
m_Lines = 0;
VERIFY(WriteString(MORE_STRING,m_CursorPosition));
VERIFY(FlushInputBuffer());
CONSOLE_CURSOR_INFO cci;
cci.bVisible = FALSE;
cci.dwSize = 100;
VERIFY(SetConsoleCursorInfo(m_hStdOut,&cci));
INPUT_RECORD InputRecord;
DWORD dwRecordsReaded;
while ((ret = ReadConsoleInput(m_hStdIn,&InputRecord,1,&dwRecordsReaded)) != FALSE)
{
ASSERT(dwRecordsReaded == 1);
if (dwRecordsReaded != 1)
break;
if (InputRecord.EventType != KEY_EVENT)
continue;
if (!InputRecord.Event.KeyEvent.bKeyDown)
continue;
if ((InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_CANCEL)||
(InputRecord.Event.KeyEvent.wVirtualKeyCode == _T('Q')))
{
VERIFY(GenerateConsoleCtrlEvent(CTRL_C_EVENT,0));
continue;
}
#ifdef UNICODE
TCHAR ch = InputRecord.Event.KeyEvent.uChar.UnicodeChar;
#else
TCHAR ch = InputRecord.Event.KeyEvent.uChar.AsciiChar;
#endif
if (ch)
break;
}
// delete "more" msg
VERIFY(WriteString(MORE_EMPTY_STRING,m_CursorPosition));
m_CursorPosition.X = 0;
cci.bVisible = TRUE;
cci.dwSize = m_blnInsetMode?m_dwInsertModeCursorHeight:m_dwOverwriteModeCursorHeight;
VERIFY(SetConsoleCursorInfo(m_hStdOut,&cci));
}
}
dwCharsWrittenAdd++;
dwCharsToWrite--;
}
return ret;
}
unsigned int CConsole::GetTabWidth()
{
return TAB_WIDTH;
}
BOOL CConsole::SetTitle(TCHAR *p)
{
return SetConsoleTitle(p);
}
BOOL CConsole::SetTextAttribute(WORD wAttributes)
{
m_wAttributes = wAttributes;
return TRUE;
}
/*
BOOL CConsole::SetInputMode(DWORD dwMode)
{
return SetConsoleMode(m_hStdIn,dwMode);
}
BOOL CConsole::SetOutputMode(DWORD dwMode)
{
return SetConsoleMode(m_hStdOut,dwMode);
}*/
BOOL CConsole::FlushInputBuffer()
{
if (m_hStdIn == INVALID_HANDLE_VALUE) return FALSE;
return FlushConsoleInputBuffer(m_hStdIn);
}
BOOL CConsole::ReadLine()
{
if (m_hStdIn == INVALID_HANDLE_VALUE) return FALSE;
if (m_hStdOut == INVALID_HANDLE_VALUE) return FALSE;
if (m_dwBufferSize == 0)
{
ASSERT(FALSE);
return FALSE;
}
if (m_pchBuffer == NULL)
{
ASSERT(FALSE);
return FALSE;
}
if (m_pchBuffer1 == NULL)
{
ASSERT(FALSE);
return FALSE;
}
if (!FlushConsoleInputBuffer(m_hStdIn)) return FALSE;
COORD FristCharCursorPosition = m_CursorPosition;
#define X_CURSOR_POSITION_FROM_OFFSET(ofs) USHORT(((FristCharCursorPosition.X + ofs)%m_BufferSize.X))
#define Y_CURSOR_POSITION_FROM_OFFSET(ofs) USHORT((FristCharCursorPosition.Y + (FristCharCursorPosition.X + ofs)/m_BufferSize.X))
//#define OFFSET_FROM_CURSOR_POSITION(pos) ((pos.Y-FristCharCursorPosition.Y)*m_BufferSize.X+pos.X-FristCharCursorPosition.X)
DWORD dwRecordsReaded;
DWORD dwCurrentCharOffset = 0;
DWORD dwLastCharOffset = 0;
BOOL ret;
BOOL blnCompletionMode = FALSE;
// unsigned __int64 nCompletionIndex = 0;
unsigned long long nCompletionIndex = 0;
DWORD dwCompletionOffset = 0;
DWORD dwCompletionStringSize = 0;
COORD CompletionPosition = FristCharCursorPosition;
m_LinesScrolled = 0;
BOOL blnOldMoreMode = m_blnMoreMode;
m_blnMoreMode = FALSE;
DWORD dwHistoryIndex = 0;
INPUT_RECORD InputRecord;
while ((ret = ReadConsoleInput(m_hStdIn,&InputRecord,1,&dwRecordsReaded)) != FALSE)
{
ASSERT(dwRecordsReaded == 1);
if (dwRecordsReaded != 1) return FALSE;
if (InputRecord.EventType != KEY_EVENT) continue;
if (!InputRecord.Event.KeyEvent.bKeyDown) continue;
#ifdef UNICODE
TCHAR ch = InputRecord.Event.KeyEvent.uChar.UnicodeChar;
#else
TCHAR ch = InputRecord.Event.KeyEvent.uChar.AsciiChar;
#endif
KeyRepeat:
if (m_LinesScrolled)
{
if (m_LinesScrolled > FristCharCursorPosition.Y) return FALSE;
FristCharCursorPosition.Y = SHORT(FristCharCursorPosition.Y - m_LinesScrolled);
if (m_LinesScrolled > CompletionPosition.Y) return FALSE;
CompletionPosition.Y = SHORT(CompletionPosition.Y - m_LinesScrolled);
m_LinesScrolled = 0;
}
// char Buf[1024];
// sprintf(Buf,"wVirtualKeyCode = %u\nchar = %u\n\n",InputRecord.Event.KeyEvent.wVirtualKeyCode,ch);
// OutputDebugString(Buf);
#ifndef NO_PASTE
if ((ch == 0x16)&&(InputRecord.Event.KeyEvent.wVirtualKeyCode == 'V'))
{
goto Paste;
}
else
#endif
if (ch == 0)
{
#ifndef NO_PASTE
if (InputRecord.Event.KeyEvent.wVirtualKeyCode == VK_INSERT)
{
if (!(InputRecord.Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED))
{
VERIFY(SetInsertMode(!m_blnInsetMode));
}
else
{
if (blnCompletionMode) blnCompletionMode = FALSE;
Paste:
if (!IsClipboardFormatAvailable(
#ifdef UNICODE
CF_UNICODETEXT
#else
CF_TEXT
#endif
))
continue;
if (!OpenClipboard(NULL))
continue;
const TCHAR *pch = NULL;
HANDLE hglb = GetClipboardData(
#ifdef UNICODE
CF_UNICODETEXT
#else
CF_TEXT
#endif
);
if (hglb != NULL)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -