Switched ConsoleDlg over to richtext

This commit is contained in:
Justin Marshall
2026-05-14 19:16:41 -07:00
parent 647911d693
commit d5f59f06e1
2 changed files with 624 additions and 167 deletions
+586 -146
View File
@@ -2,26 +2,9 @@
===========================================================================
IceTech GPL Source Code
Copyright (C) 2026 Justin Marshall
Copyright (C) 2026 Justin Marshall
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
IceTech Source Code 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 3 of the License, or
(at your option) any later version.
IceTech Source Code 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 IceTech Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the IceTech Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IceTech Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
===========================================================================
*/
@@ -37,52 +20,441 @@ If you have questions concerning this license or the applicable additional terms
// CConsoleDlg dialog
IMPLEMENT_DYNCREATE(CConsoleDlg, CDialog)
CConsoleDlg::CConsoleDlg(CWnd* pParent /*=NULL*/)
: CDialog(CConsoleDlg::IDD)
: CDialog(CConsoleDlg::IDD, pParent)
{
currentHistoryPosition = -1;
currentCommand = "";
currentHistoryPosition = -1;
currentCommand = "";
saveCurrentCommand = true;
}
CConsoleDlg::~CConsoleDlg()
{
if (blackBrush.GetSafeHandle() != NULL) {
blackBrush.DeleteObject();
}
}
void CConsoleDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT_CONSOLE, editConsole);
// Do not DDX IDC_EDIT_CONSOLE here.
// The resource control can stay as a normal EDIT placeholder.
// OnInitDialog destroys it and creates the RichEdit in its place.
DDX_Control(pDX, IDC_EDIT_INPUT, editInput);
}
void CConsoleDlg::AddText( const char *msg ) {
idStr work;
CString work2;
work = msg;
work.RemoveColors();
work = CEntityDlg::TranslateString( work.c_str() );
editConsole.GetWindowText( work2 );
int len = work2.GetLength();
if ( len + work.Length() > (int)editConsole.GetLimitText() ) {
work2 = work2.Right( editConsole.GetLimitText() * 0.75 );
len = work2.GetLength();
editConsole.SetWindowText(work2);
}
editConsole.SetSel( len, len );
editConsole.ReplaceSel( work );
}
BEGIN_MESSAGE_MAP(CConsoleDlg, CDialog)
ON_WM_SIZE()
ON_WM_SETFOCUS()
ON_WM_ACTIVATE()
ON_WM_CTLCOLOR()
END_MESSAGE_MAP()
// CConsoleDlg message handlers
BOOL CConsoleDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Needed before creating CRichEditCtrl.
// Safe if already initialized elsewhere.
AfxInitRichEdit2();
if (blackBrush.GetSafeHandle() == NULL) {
blackBrush.CreateSolidBrush(RGB(0, 0, 0));
}
CreateRichConsoleFromPlaceholder();
SetupRichConsoleDefaults();
if (editInput.GetSafeHwnd() != NULL) {
editInput.SetLimitText(1024);
editInput.SetWindowText("");
}
return TRUE;
}
void CConsoleDlg::CreateRichConsoleFromPlaceholder()
{
CWnd* oldConsole = GetDlgItem(IDC_EDIT_CONSOLE);
if (oldConsole == NULL || oldConsole->GetSafeHwnd() == NULL) {
return;
}
CRect rc;
oldConsole->GetWindowRect(&rc);
ScreenToClient(&rc);
oldConsole->DestroyWindow();
DWORD style =
WS_CHILD |
WS_VISIBLE |
WS_TABSTOP |
WS_VSCROLL |
ES_MULTILINE |
ES_AUTOVSCROLL |
ES_READONLY |
ES_NOHIDESEL |
ES_SAVESEL;
// Older MFC CRichEditCtrl::Create only takes 4 args.
// Do not use CreateEx here.
editConsole.Create(
style,
rc,
this,
IDC_EDIT_CONSOLE
);
}
void CConsoleDlg::SetupRichConsoleDefaults()
{
if (editConsole.GetSafeHwnd() == NULL) {
return;
}
editConsole.SetEventMask(0);
editConsole.SetOptions(ECOOP_OR, ECO_AUTOVSCROLL);
editConsole.SetReadOnly(TRUE);
// CRichEditCtrl uses LimitText(), not SetLimitText().
editConsole.LimitText(1024 * 1024);
editConsole.SetBackgroundColor(FALSE, RGB(0, 0, 0));
CHARFORMAT cf;
memset(&cf, 0, sizeof(cf));
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE;
cf.crTextColor = ICE_CONSOLE_DEFAULT_COLOR;
cf.yHeight = 180; // 9pt
lstrcpyn(cf.szFaceName, "Consolas", LF_FACESIZE);
editConsole.SetDefaultCharFormat(cf);
editConsole.SetSel(0, -1);
editConsole.SetSelectionCharFormat(cf);
editConsole.SetSel(-1, -1);
}
CString CConsoleDlg::NormalizeNewlines(const CString& in) const
{
CString out;
out.Preallocate(in.GetLength() + 16);
for (int i = 0; i < in.GetLength(); i++) {
TCHAR c = in[i];
if (c == '\r') {
if (i + 1 < in.GetLength() && in[i + 1] == '\n') {
out += "\r\n";
i++;
}
else {
out += "\r\n";
}
}
else if (c == '\n') {
out += "\r\n";
}
else {
out += c;
}
}
return out;
}
COLORREF CConsoleDlg::DoomColorForIndex(char c) const
{
switch (c) {
case '0':
return RGB(0, 0, 0); // black
case '1':
return RGB(255, 64, 64); // red
case '2':
return RGB(64, 255, 64); // green
case '3':
return RGB(255, 255, 64); // yellow
case '4':
return RGB(80, 140, 255); // blue
case '5':
return RGB(64, 255, 255); // cyan
case '6':
return RGB(255, 64, 255); // magenta
case '7':
return RGB(230, 230, 230); // white
case '8':
return RGB(160, 160, 160); // gray
case '9':
return RGB(255, 150, 32); // orange
case 'r':
case 'R':
return RGB(255, 64, 64);
case 'g':
case 'G':
return RGB(64, 255, 64);
case 'y':
case 'Y':
return RGB(255, 255, 64);
case 'b':
case 'B':
return RGB(80, 140, 255);
case 'c':
case 'C':
return RGB(64, 255, 255);
case 'm':
case 'M':
return RGB(255, 64, 255);
case 'w':
case 'W':
return RGB(230, 230, 230);
default:
return ICE_CONSOLE_DEFAULT_COLOR;
}
}
static bool ConsoleStartsWithNoCase(const char* s, const char* prefix)
{
if (s == NULL || prefix == NULL) {
return false;
}
while (*prefix != '\0') {
char a = *s;
char b = *prefix;
if (a >= 'A' && a <= 'Z') {
a = a - 'A' + 'a';
}
if (b >= 'A' && b <= 'Z') {
b = b - 'A' + 'a';
}
if (a != b) {
return false;
}
s++;
prefix++;
}
return true;
}
COLORREF CConsoleDlg::DoomColorForName(const char* name, int& consumed) const
{
consumed = 0;
struct colorName_t {
const char* name;
COLORREF color;
};
static const colorName_t names[] = {
{ "S_COLOR_BLACK", RGB(0, 0, 0) },
{ "S_COLOR_RED", RGB(255, 64, 64) },
{ "S_COLOR_GREEN", RGB(64, 255, 64) },
{ "S_COLOR_YELLOW", RGB(255, 255, 64) },
{ "S_COLOR_BLUE", RGB(80, 140, 255) },
{ "S_COLOR_CYAN", RGB(64, 255, 255) },
{ "S_COLOR_MAGENTA", RGB(255, 64, 255) },
{ "S_COLOR_WHITE", RGB(230, 230, 230) },
{ "S_COLOR_GRAY", RGB(160, 160, 160) },
{ "S_COLOR_GREY", RGB(160, 160, 160) },
{ "S_COLOR_ORANGE", RGB(255, 150, 32) },
{ "COLOR_BLACK", RGB(0, 0, 0) },
{ "COLOR_RED", RGB(255, 64, 64) },
{ "COLOR_GREEN", RGB(64, 255, 64) },
{ "COLOR_YELLOW", RGB(255, 255, 64) },
{ "COLOR_BLUE", RGB(80, 140, 255) },
{ "COLOR_CYAN", RGB(64, 255, 255) },
{ "COLOR_MAGENTA", RGB(255, 64, 255) },
{ "COLOR_WHITE", RGB(230, 230, 230) },
{ "COLOR_GRAY", RGB(160, 160, 160) },
{ "COLOR_GREY", RGB(160, 160, 160) },
{ "COLOR_ORANGE", RGB(255, 150, 32) }
};
for (int i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
if (ConsoleStartsWithNoCase(name, names[i].name)) {
consumed = (int)strlen(names[i].name);
return names[i].color;
}
}
return ICE_CONSOLE_DEFAULT_COLOR;
}
bool CConsoleDlg::TryConsumeColorToken(const char* s, int& consumed, COLORREF& color) const
{
consumed = 0;
color = ICE_CONSOLE_DEFAULT_COLOR;
if (s == NULL || s[0] == '\0') {
return false;
}
// Doom/idTech style color escape: ^1, ^2, ^7, etc.
if (s[0] == '^' && s[1] != '\0') {
// ^^ means literal caret, not a color.
if (s[1] == '^') {
return false;
}
color = DoomColorForIndex(s[1]);
consumed = 2;
return true;
}
// Optional support if some code emits literal token names.
int namedConsumed = 0;
COLORREF namedColor = DoomColorForName(s, namedConsumed);
if (namedConsumed > 0) {
color = namedColor;
consumed = namedConsumed;
return true;
}
return false;
}
void CConsoleDlg::AppendConsoleRun(const CString& text, COLORREF color)
{
if (text.IsEmpty() || editConsole.GetSafeHwnd() == NULL) {
return;
}
CString normalized = NormalizeNewlines(text);
editConsole.SetReadOnly(FALSE);
int len = editConsole.GetTextLength();
editConsole.SetSel(len, len);
CHARFORMAT cf;
memset(&cf, 0, sizeof(cf));
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_COLOR | CFM_FACE | CFM_SIZE;
cf.crTextColor = color;
cf.yHeight = 180;
lstrcpyn(cf.szFaceName, "Consolas", LF_FACESIZE);
editConsole.SetSelectionCharFormat(cf);
editConsole.ReplaceSel(normalized, FALSE);
editConsole.SetReadOnly(TRUE);
}
void CConsoleDlg::TrimConsoleIfNeeded()
{
if (editConsole.GetSafeHwnd() == NULL) {
return;
}
const int maxChars = 512 * 1024;
const int trimToChars = 384 * 1024;
int len = editConsole.GetTextLength();
if (len <= maxChars) {
return;
}
int removeCount = len - trimToChars;
editConsole.SetReadOnly(FALSE);
editConsole.SetSel(0, removeCount);
editConsole.ReplaceSel("", FALSE);
editConsole.SetReadOnly(TRUE);
}
void CConsoleDlg::AppendConsoleTextColored(const char* text)
{
if (text == NULL || editConsole.GetSafeHwnd() == NULL) {
return;
}
COLORREF currentColor = ICE_CONSOLE_DEFAULT_COLOR;
CString run;
const char* p = text;
while (*p != '\0') {
int consumed = 0;
COLORREF newColor = ICE_CONSOLE_DEFAULT_COLOR;
if (TryConsumeColorToken(p, consumed, newColor)) {
if (!run.IsEmpty()) {
AppendConsoleRun(run, currentColor);
run.Empty();
}
currentColor = newColor;
p += consumed;
continue;
}
if (p[0] == '^' && p[1] == '^') {
run += '^';
p += 2;
continue;
}
run += *p;
p++;
}
if (!run.IsEmpty()) {
AppendConsoleRun(run, currentColor);
}
TrimConsoleIfNeeded();
int len = editConsole.GetTextLength();
editConsole.SetSel(len, len);
editConsole.SendMessage(EM_SCROLLCARET, 0, 0);
}
void CConsoleDlg::AddText(const char* msg)
{
if (msg == NULL || editConsole.GetSafeHwnd() == NULL) {
return;
}
idStr work;
work = msg;
// DO NOT call RemoveColors() here.
// The RichEdit append path consumes Doom color codes and applies colors.
work = CEntityDlg::TranslateString(work.c_str());
AppendConsoleTextColored(work.c_str());
}
void CConsoleDlg::OnSize(UINT nType, int cx, int cy)
{
@@ -92,158 +464,212 @@ void CConsoleDlg::OnSize(UINT nType, int cx, int cy)
return;
}
CRect rect, crect;
GetWindowRect(rect);
editInput.GetWindowRect(crect);
CRect clientRect;
GetClientRect(&clientRect);
editInput.SetWindowPos(NULL, 4, rect.Height() - 4 - crect.Height(), rect.Width() - 8, crect.Height(), SWP_SHOWWINDOW);
editConsole.SetWindowPos(NULL, 4, 4, rect.Width() - 8, rect.Height() - crect.Height() - 8, SWP_SHOWWINDOW);
CRect inputRect;
editInput.GetWindowRect(&inputRect);
const int margin = 4;
const int inputHeight = inputRect.Height();
editInput.SetWindowPos(
NULL,
margin,
clientRect.Height() - margin - inputHeight,
clientRect.Width() - margin * 2,
inputHeight,
SWP_SHOWWINDOW
);
if (editConsole.GetSafeHwnd() != NULL) {
editConsole.SetWindowPos(
NULL,
margin,
margin,
clientRect.Width() - margin * 2,
clientRect.Height() - inputHeight - margin * 3,
SWP_SHOWWINDOW
);
}
}
BOOL CConsoleDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->hwnd == editInput.GetSafeHwnd()) {
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE ) {
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) {
Select_Deselect();
g_pParentWnd->SetFocus ();
g_pParentWnd->SetFocus();
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN ) {
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
ExecuteCommand();
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE ) {
if (pMsg->wParam == VK_ESCAPE) {
g_pParentWnd->GetCamera()->SetFocus();
Select_Deselect();
}
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_UP ) {
//save off the current in-progress command so we can get back to it
if ( saveCurrentCommand == true ) {
CString str;
editInput.GetWindowText ( str );
currentCommand = str.GetBuffer ( 0 );
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_UP) {
// Save off the current in-progress command so we can get back to it.
if (saveCurrentCommand == true) {
CString str;
editInput.GetWindowText(str);
currentCommand = str.GetBuffer(0);
saveCurrentCommand = false;
}
if ( consoleHistory.Num () > 0 ) {
editInput.SetWindowText ( consoleHistory[currentHistoryPosition] );
int selLocation = consoleHistory[currentHistoryPosition].Length ();
editInput.SetSel ( selLocation , selLocation + 1);
}
if ( currentHistoryPosition > 0) {
--currentHistoryPosition;
}
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_DOWN ) {
int selLocation = 0;
if ( currentHistoryPosition < consoleHistory.Num () - 1 ) {
++currentHistoryPosition;
editInput.SetWindowText ( consoleHistory[currentHistoryPosition] );
selLocation = consoleHistory[currentHistoryPosition].Length ();
}
else {
editInput.SetWindowText ( currentCommand );
selLocation = currentCommand.Length ();
currentCommand.Clear ();
saveCurrentCommand = true;
}
editInput.SetSel ( selLocation , selLocation + 1);
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB ) {
common->Printf ( "Command History\n----------------\n" );
for ( int i = 0 ; i < consoleHistory.Num ();i++ )
{
common->Printf ( "[cmd %d]: %s\n" , i , consoleHistory[i].c_str() );
}
common->Printf ( "----------------\n" );
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_NEXT) {
editConsole.LineScroll ( 10 );
if (consoleHistory.Num() > 0) {
if (currentHistoryPosition < 0) {
currentHistoryPosition = consoleHistory.Num() - 1;
}
if (currentHistoryPosition >= consoleHistory.Num()) {
currentHistoryPosition = consoleHistory.Num() - 1;
}
editInput.SetWindowText(consoleHistory[currentHistoryPosition]);
int selLocation = consoleHistory[currentHistoryPosition].Length();
editInput.SetSel(selLocation, selLocation);
if (currentHistoryPosition > 0) {
--currentHistoryPosition;
}
}
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_PRIOR ) {
editConsole.LineScroll ( -10 );
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_DOWN) {
int selLocation = 0;
if (currentHistoryPosition < consoleHistory.Num() - 1) {
++currentHistoryPosition;
editInput.SetWindowText(consoleHistory[currentHistoryPosition]);
selLocation = consoleHistory[currentHistoryPosition].Length();
}
else {
editInput.SetWindowText(currentCommand);
selLocation = currentCommand.Length();
currentCommand.Clear();
saveCurrentCommand = true;
}
editInput.SetSel(selLocation, selLocation);
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_HOME ) {
editConsole.LineScroll ( -editConsole.GetLineCount() );
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) {
common->Printf("Command History\n----------------\n");
for (int i = 0; i < consoleHistory.Num(); i++) {
common->Printf("[cmd %d]: %s\n", i, consoleHistory[i].c_str());
}
common->Printf("----------------\n");
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_END ) {
editConsole.LineScroll ( editConsole.GetLineCount() );
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_NEXT) {
if (editConsole.GetSafeHwnd() != NULL) {
editConsole.LineScroll(10);
}
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_PRIOR) {
if (editConsole.GetSafeHwnd() != NULL) {
editConsole.LineScroll(-10);
}
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_HOME) {
if (editConsole.GetSafeHwnd() != NULL) {
editConsole.LineScroll(-editConsole.GetLineCount());
}
return TRUE;
}
if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_END) {
if (editConsole.GetSafeHwnd() != NULL) {
editConsole.LineScroll(editConsole.GetLineCount());
}
return TRUE;
}
}
return CDialog::PreTranslateMessage(pMsg);
}
void CConsoleDlg::OnSetFocus(CWnd* pOldWnd) {
void CConsoleDlg::OnSetFocus(CWnd* pOldWnd)
{
CDialog::OnSetFocus(pOldWnd);
editInput.SetFocus();
if (editInput.GetSafeHwnd() != NULL) {
editInput.SetFocus();
}
}
void CConsoleDlg::SetConsoleText ( const idStr& text ) {
editInput.Clear ();
editInput.SetWindowText ( text.c_str() );
void CConsoleDlg::SetConsoleText(const idStr& text)
{
if (editInput.GetSafeHwnd() != NULL) {
editInput.Clear();
editInput.SetWindowText(text.c_str());
}
}
void CConsoleDlg::ExecuteCommand ( const idStr& cmd ) {
void CConsoleDlg::ExecuteCommand(const idStr& cmd)
{
CString str;
if ( cmd.Length() > 0 ) {
if (cmd.Length() > 0) {
str = cmd;
}
else {
editInput.GetWindowText(str);
}
if ( str != "" ) {
if (str != "") {
editInput.SetWindowText("");
common->Printf("%s\n", str.GetBuffer(0));
//avoid adding multiple identical commands in a row
int index = consoleHistory.Num ();
common->Printf("%s\n", str.GetBuffer(0));
if ( index == 0 || str.GetBuffer(0) != consoleHistory[index-1]) {
//keep the history to 16 commands, removing the oldest command
if ( consoleHistory.Num () > 16 ) {
consoleHistory.RemoveIndex ( 0 );
// Avoid adding multiple identical commands in a row.
int index = consoleHistory.Num();
if (index == 0 || str.GetBuffer(0) != consoleHistory[index - 1]) {
// Keep the history to 16 commands, removing the oldest command.
if (consoleHistory.Num() > 16) {
consoleHistory.RemoveIndex(0);
}
currentHistoryPosition = consoleHistory.Append ( str.GetBuffer (0) );
currentHistoryPosition = consoleHistory.Append(str.GetBuffer(0));
}
else {
currentHistoryPosition = consoleHistory.Num () - 1;
currentHistoryPosition = consoleHistory.Num() - 1;
}
currentCommand.Clear ();
currentCommand.Clear();
saveCurrentCommand = true;
bool propogateCommand = true;
//process some of our own special commands
if ( str.CompareNoCase ( "clear" ) == 0) {
editConsole.SetSel ( 0 , -1 );
editConsole.Clear ();
}
else if ( str.CompareNoCase ( "edit" ) == 0) {
// Process some of our own special commands.
if (str.CompareNoCase("clear") == 0) {
if (editConsole.GetSafeHwnd() != NULL) {
editConsole.SetReadOnly(FALSE);
editConsole.SetSel(0, -1);
editConsole.ReplaceSel("", FALSE);
editConsole.SetReadOnly(TRUE);
}
propogateCommand = false;
}
if ( propogateCommand ) {
cmdSystem->BufferCommandText( CMD_EXEC_NOW, str );
else if (str.CompareNoCase("edit") == 0) {
propogateCommand = false;
}
if (propogateCommand) {
cmdSystem->BufferCommandText(CMD_EXEC_NOW, str);
}
Sys_UpdateWindows(W_ALL);
@@ -254,8 +680,22 @@ void CConsoleDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
CDialog::OnActivate(nState, pWndOther, bMinimized);
if ( nState == WA_ACTIVE || nState == WA_CLICKACTIVE )
{
editInput.SetFocus();
}
if (nState == WA_ACTIVE || nState == WA_CLICKACTIVE) {
if (editInput.GetSafeHwnd() != NULL) {
editInput.SetFocus();
}
}
}
HBRUSH CConsoleDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
if (pWnd != NULL && pWnd->GetSafeHwnd() == editInput.GetSafeHwnd()) {
pDC->SetBkColor(RGB(0, 0, 0));
pDC->SetTextColor(ICE_CONSOLE_DEFAULT_COLOR);
return (HBRUSH)blackBrush.GetSafeHandle();
}
return hbr;
}
+38 -21
View File
@@ -2,9 +2,9 @@
===========================================================================
IceTech GPL Source Code
Copyright (C) 2026 Justin Marshall
Copyright (C) 2026 Justin Marshall
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
This file is part of the IceTech GPL Source Code (?IceTech Source Code?).
IceTech Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,17 +16,15 @@ 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 IceTech Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the IceTech Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the IceTech Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Justin Marshall, justinmarshall20@gmail.com
===========================================================================
*/
#pragma once
#include "afxwin.h"
#include "afxrich.h"
#define ICE_CONSOLE_DEFAULT_COLOR RGB(64, 255, 255)
// CConsoleDlg dialog
@@ -36,31 +34,50 @@ class CConsoleDlg : public CDialog
DECLARE_DYNCREATE(CConsoleDlg)
public:
CConsoleDlg(CWnd* pParent = NULL); // standard constructor
CConsoleDlg(CWnd* pParent = NULL);
virtual ~CConsoleDlg();
// Dialog Data
enum { IDD = IDD_DIALOG_CONSOLE };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
virtual void DoDataExchange(CDataExchange* pDX);
virtual BOOL OnInitDialog();
DECLARE_MESSAGE_MAP()
public:
CEdit editConsole;
CRichEditCtrl editConsole;
CEdit editInput;
void AddText(const char *msg);
void SetConsoleText ( const idStr& text );
void ExecuteCommand ( const idStr& cmd = "" );
void AddText(const char* msg);
void SetConsoleText(const idStr& text);
void ExecuteCommand(const idStr& cmd = "");
idStr consoleStr;
idStrList consoleHistory;
idStr currentCommand;
int currentHistoryPosition;
idStrList consoleHistory;
idStr currentCommand;
int currentHistoryPosition;
bool saveCurrentCommand;
afx_msg void OnSize(UINT nType, int cx, int cy);
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnSetFocus(CWnd* pOldWnd);
afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
};
afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
private:
CBrush blackBrush;
void CreateRichConsoleFromPlaceholder();
void SetupRichConsoleDefaults();
void AppendConsoleTextColored(const char* text);
void AppendConsoleRun(const CString& text, COLORREF color);
void TrimConsoleIfNeeded();
bool TryConsumeColorToken(const char* s, int& consumed, COLORREF& color) const;
COLORREF DoomColorForIndex(char c) const;
COLORREF DoomColorForName(const char* name, int& consumed) const;
CString NormalizeNewlines(const CString& in) const;
};