Richard Boegli's CnC_Generals_Zero_Hour Fork WIP
This is documentation of Richard Boegil's Zero Hour Fork
 
Loading...
Searching...
No Matches
debug_io_con.cpp
Go to the documentation of this file.
1/*
2** Command & Conquer Generals Zero Hour(tm)
3** Copyright 2025 Electronic Arts Inc.
4**
5** This program is free software: you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation, either version 3 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
20// $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_io_con.cpp $
21// $Author: mhoffe $
22// $Revision: #1 $
23// $DateTime: 2003/07/03 11:55:26 $
24//
25// ©2003 Electronic Arts
26//
27// Debug I/O class con (console window)
29#include "_pch.h"
30#include <stdlib.h>
31#include <new> // needed for placement new prototype
32
34 m_inputUsed(0), m_inputRead(0)
35{
36 // check: is there already a console window open?
37 m_allocatedConsole=AllocConsole()!=0;
38 if (m_allocatedConsole)
39 {
40 HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
41 SetConsoleMode(h,0);
42
43 // make screen buffer same size as currently displayed area
44 // (prevents that our input line gets scrolled out of view)
45 h=GetStdHandle(STD_OUTPUT_HANDLE);
46 CONSOLE_SCREEN_BUFFER_INFO info;
47 GetConsoleScreenBufferInfo(h,&info);
48
49 COORD newSize;
50 newSize.X=info.srWindow.Right+1;
51 newSize.Y=info.srWindow.Bottom+1;
52 SetConsoleScreenBufferSize(h,newSize);
53
54 // hide cursor
55 CONSOLE_CURSOR_INFO ci;
56 ci.dwSize=1;
57 ci.bVisible=FALSE;
58 SetConsoleCursorInfo(h,&ci);
59
60 Write(StringType::Other,NULL,"\n\nEA/Debug console open\n\n");
61 }
62}
63
65{
66 // close console if we allocated it
67 if (m_allocatedConsole)
68 FreeConsole();
69}
70
71int DebugIOCon::Read(char *buf, int maxchar)
72{
73 // We are not supporting reading from the console
74 // unless we allocated that console ourselves.
75 // The reason for that is that if we didn't allocate
76 // the console ourselves we're running as a console
77 // process and if we'd be reading data from the console
78 // we would probably be snatching away keyboard data
79 // for the process that is using that console.
80 if (!m_allocatedConsole)
81 return 0;
82
83 // are we doing a continuous read?
84 if (m_inputRead)
85 {
86 int numRead;
87 if (maxchar>m_inputUsed-m_inputRead)
88 {
89 // return all
90 numRead=m_inputUsed-m_inputRead;
91 memcpy(buf,m_input+m_inputRead,numRead);
92 m_inputRead=m_inputUsed=0;
93 }
94 else
95 {
96 // return partially
97 numRead=maxchar;
98 memcpy(buf,m_input+m_inputRead,numRead);
99 m_inputRead+=maxchar;
100 }
101 return numRead;
102 }
103
104 // update our input buffer
105 HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
106 bool returnChars=false;
107 for (;;)
108 {
109 DWORD dwRecords;
110 if (!GetNumberOfConsoleInputEvents(h,&dwRecords))
111 break;
112 if (!dwRecords)
113 break;
114
115 INPUT_RECORD record;
116 ReadConsoleInput(h,&record,1,&dwRecords);
117 if (record.EventType!=KEY_EVENT)
118 continue;
119
120 KEY_EVENT_RECORD &key=record.Event.KeyEvent;
121 if (!key.bKeyDown||!key.uChar.AsciiChar)
122 continue;
123
124 if (key.uChar.AsciiChar=='\r'||
125 key.uChar.AsciiChar=='\n')
126 {
127 m_input[m_inputUsed++]='\n';
128 returnChars=true;
129 break;
130 }
131
133
134 if (key.uChar.AsciiChar=='\b')
135 {
136 if (m_inputUsed)
137 m_inputUsed--;
138 }
139 else if (((unsigned char)key.uChar.AsciiChar)>=' ')
140 {
141 if (m_inputUsed<sizeof(m_input)-1)
142 m_input[m_inputUsed++]=key.uChar.AsciiChar;
143 }
144 }
145
146 // update screen
147 h=GetStdHandle(STD_OUTPUT_HANDLE);
148 CONSOLE_SCREEN_BUFFER_INFO info;
149 GetConsoleScreenBufferInfo(h,&info);
150 CHAR_INFO ci[sizeof(m_input)+1];
151 for (unsigned k=0;k<=sizeof(m_input);k++)
152 {
153 ci[k].Char.AsciiChar=k<m_inputUsed?m_input[k]:' ';
154 ci[k].Attributes=BACKGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_GREEN
155 |FOREGROUND_RED|FOREGROUND_INTENSITY;
156 }
157
158 // fake another cursor
159 if (GetTickCount()&512)
160 ci[m_inputUsed].Attributes=BACKGROUND_BLUE|BACKGROUND_GREEN
161 |BACKGROUND_RED|BACKGROUND_INTENSITY|FOREGROUND_GREEN;
162
163 COORD srcSize,srcCoord;
164 srcSize.X=sizeof(m_input); srcSize.Y=1;
165 srcCoord.X=srcCoord.Y=0;
166
167 SMALL_RECT r;
168 r.Left=r.Top=r.Bottom=0; r.Right=info.dwSize.X-1;
169 WriteConsoleOutput(h,ci+(m_inputUsed<=info.dwSize.X?0:m_inputUsed-info.dwSize.X),
170 srcSize,srcCoord,&r);
171
172 // return data now?
173 if (returnChars&&m_inputUsed>1)
174 {
175 *buf=*m_input;
176 m_inputRead=1;
177 return 1;
178 }
179
180 return 0;
181}
182
183void DebugIOCon::Write(StringType type, const char *src, const char *str)
184{
185 if (type==StringType::StructuredCmdReply||!str)
186 return;
187
188 DWORD dwDummy;
189 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),str,strlen(str),&dwDummy,NULL);
190}
191
192void DebugIOCon::Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
193 unsigned argn, const char * const * argv)
194{
195 if (!cmd||!strcmp(cmd,"help"))
196 {
197 dbg << "con I/O help:\n"
198 " add [ <width> [ <height> ] ]\n"
199 " create con I/O (optionally specifying the window size)\n";
200 }
201 else if (!strcmp(cmd,"add"))
202 {
203 if (argn>0&&m_allocatedConsole)
204 {
205 // resize our console area
206 HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
207 COORD newSize;
208 newSize.X=atoi(argv[0]);
209 newSize.Y=argn>1?atoi(argv[1]):25;
210 SMALL_RECT sr;
211 sr.Left=sr.Top=0;
212 sr.Right=newSize.X-1;
213 sr.Bottom=newSize.Y-1;
214 SetConsoleWindowInfo(h,TRUE,&sr);
215 SetConsoleScreenBufferSize(h,newSize);
216 SetConsoleWindowInfo(h,TRUE,&sr);
217 }
218 }
219}
220
221DebugIOInterface *DebugIOCon::Create(void)
222{
223 return new (DebugAllocMemory(sizeof(DebugIOCon))) DebugIOCon();
224}
225
227{
228 this->~DebugIOCon();
229 DebugFreeMemory(this);
230}
#define NULL
Definition BaseType.h:92
#define TRUE
Definition BaseType.h:109
#define FALSE
Definition BaseType.h:113
unsigned long DWORD
Definition bittype.h:57
Debug module main class (singleton).
Definition debug_debug.h:45
static DebugIOInterface * Create(void)
virtual void Write(StringType type, const char *src, const char *str)
Write out some characters differentiated by the log string type.
virtual ~DebugIOCon()
virtual void Execute(class Debug &dbg, const char *cmd, bool structuredCmd, unsigned argn, const char *const *argv)
I/O class specific command.
virtual void Delete(void)
Destroys the current I/O class instance.
virtual int Read(char *buf, int maxchar)
Retrieves up to the given number of characters from a command input source.
StringType
List of possible log string types.
Definition debug_io.h:67
@ Other
some other message
Definition debug_io.h:90
@ StructuredCmdReply
Structured command reply, see Structured command reply.
Definition debug_io.h:87
void * DebugAllocMemory(unsigned numBytes)
void DebugFreeMemory(void *ptr)