| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** 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 3 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. If not, see <http://www.gnu.org/licenses/>.
- */
- /////////////////////////////////////////////////////////////////////////EA-V1
- // $File: //depot/GeneralsMD/Staging/code/Libraries/Source/debug/debug_io_con.cpp $
- // $Author: mhoffe $
- // $Revision: #1 $
- // $DateTime: 2003/07/03 11:55:26 $
- //
- // ©2003 Electronic Arts
- //
- // Debug I/O class con (console window)
- //////////////////////////////////////////////////////////////////////////////
- #include "_pch.h"
- #include <stdlib.h>
- #include <new> // needed for placement new prototype
- DebugIOCon::DebugIOCon(void):
- m_inputUsed(0), m_inputRead(0)
- {
- // check: is there already a console window open?
- m_allocatedConsole=AllocConsole()!=0;
- if (m_allocatedConsole)
- {
- HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
- SetConsoleMode(h,0);
- // make screen buffer same size as currently displayed area
- // (prevents that our input line gets scrolled out of view)
- h=GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo(h,&info);
- COORD newSize;
- newSize.X=info.srWindow.Right+1;
- newSize.Y=info.srWindow.Bottom+1;
- SetConsoleScreenBufferSize(h,newSize);
- // hide cursor
- CONSOLE_CURSOR_INFO ci;
- ci.dwSize=1;
- ci.bVisible=FALSE;
- SetConsoleCursorInfo(h,&ci);
- Write(StringType::Other,NULL,"\n\nEA/Debug console open\n\n");
- }
- }
- DebugIOCon::~DebugIOCon()
- {
- // close console if we allocated it
- if (m_allocatedConsole)
- FreeConsole();
- }
- int DebugIOCon::Read(char *buf, int maxchar)
- {
- // We are not supporting reading from the console
- // unless we allocated that console ourselves.
- // The reason for that is that if we didn't allocate
- // the console ourselves we're running as a console
- // process and if we'd be reading data from the console
- // we would probably be snatching away keyboard data
- // for the process that is using that console.
- if (!m_allocatedConsole)
- return 0;
- // are we doing a continuous read?
- if (m_inputRead)
- {
- int numRead;
- if (maxchar>m_inputUsed-m_inputRead)
- {
- // return all
- numRead=m_inputUsed-m_inputRead;
- memcpy(buf,m_input+m_inputRead,numRead);
- m_inputRead=m_inputUsed=0;
- }
- else
- {
- // return partially
- numRead=maxchar;
- memcpy(buf,m_input+m_inputRead,numRead);
- m_inputRead+=maxchar;
- }
- return numRead;
- }
- // update our input buffer
- HANDLE h=GetStdHandle(STD_INPUT_HANDLE);
- bool returnChars=false;
- for (;;)
- {
- DWORD dwRecords;
- if (!GetNumberOfConsoleInputEvents(h,&dwRecords))
- break;
- if (!dwRecords)
- break;
- INPUT_RECORD record;
- ReadConsoleInput(h,&record,1,&dwRecords);
- if (record.EventType!=KEY_EVENT)
- continue;
- KEY_EVENT_RECORD &key=record.Event.KeyEvent;
- if (!key.bKeyDown||!key.uChar.AsciiChar)
- continue;
- if (key.uChar.AsciiChar=='\r'||
- key.uChar.AsciiChar=='\n')
- {
- m_input[m_inputUsed++]='\n';
- returnChars=true;
- break;
- }
- /// @todo_opt if somebody wants this can be improved by adding support for cursor keys, history, etc
- if (key.uChar.AsciiChar=='\b')
- {
- if (m_inputUsed)
- m_inputUsed--;
- }
- else if (((unsigned char)key.uChar.AsciiChar)>=' ')
- {
- if (m_inputUsed<sizeof(m_input)-1)
- m_input[m_inputUsed++]=key.uChar.AsciiChar;
- }
- }
- // update screen
- h=GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO info;
- GetConsoleScreenBufferInfo(h,&info);
- CHAR_INFO ci[sizeof(m_input)+1];
- for (unsigned k=0;k<=sizeof(m_input);k++)
- {
- ci[k].Char.AsciiChar=k<m_inputUsed?m_input[k]:' ';
- ci[k].Attributes=BACKGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_GREEN
- |FOREGROUND_RED|FOREGROUND_INTENSITY;
- }
- // fake another cursor
- if (GetTickCount()&512)
- ci[m_inputUsed].Attributes=BACKGROUND_BLUE|BACKGROUND_GREEN
- |BACKGROUND_RED|BACKGROUND_INTENSITY|FOREGROUND_GREEN;
-
- COORD srcSize,srcCoord;
- srcSize.X=sizeof(m_input); srcSize.Y=1;
- srcCoord.X=srcCoord.Y=0;
- SMALL_RECT r;
- r.Left=r.Top=r.Bottom=0; r.Right=info.dwSize.X-1;
- WriteConsoleOutput(h,ci+(m_inputUsed<=info.dwSize.X?0:m_inputUsed-info.dwSize.X),
- srcSize,srcCoord,&r);
- // return data now?
- if (returnChars&&m_inputUsed>1)
- {
- *buf=*m_input;
- m_inputRead=1;
- return 1;
- }
- return 0;
- }
- void DebugIOCon::Write(StringType type, const char *src, const char *str)
- {
- if (type==StringType::StructuredCmdReply||!str)
- return;
- DWORD dwDummy;
- WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),str,strlen(str),&dwDummy,NULL);
- }
- void DebugIOCon::Execute(class Debug& dbg, const char *cmd, bool structuredCmd,
- unsigned argn, const char * const * argv)
- {
- if (!cmd||!strcmp(cmd,"help"))
- {
- dbg << "con I/O help:\n"
- " add [ <width> [ <height> ] ]\n"
- " create con I/O (optionally specifying the window size)\n";
- }
- else if (!strcmp(cmd,"add"))
- {
- if (argn>0&&m_allocatedConsole)
- {
- // resize our console area
- HANDLE h=GetStdHandle(STD_OUTPUT_HANDLE);
- COORD newSize;
- newSize.X=atoi(argv[0]);
- newSize.Y=argn>1?atoi(argv[1]):25;
- SMALL_RECT sr;
- sr.Left=sr.Top=0;
- sr.Right=newSize.X-1;
- sr.Bottom=newSize.Y-1;
- SetConsoleWindowInfo(h,TRUE,&sr);
- SetConsoleScreenBufferSize(h,newSize);
- SetConsoleWindowInfo(h,TRUE,&sr);
- }
- }
- }
- DebugIOInterface *DebugIOCon::Create(void)
- {
- return new (DebugAllocMemory(sizeof(DebugIOCon))) DebugIOCon();
- }
- void DebugIOCon::Delete(void)
- {
- this->~DebugIOCon();
- DebugFreeMemory(this);
- }
|