mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-23 03:58:59 +00:00
547 lines
11 KiB
C++
547 lines
11 KiB
C++
|
/*
|
||
|
* $Logfile: /DescentIII/Main/win32/wincon.cpp $
|
||
|
* $Revision: 11 $
|
||
|
* $Date: 4/07/99 10:56a $
|
||
|
* $Author: Matt $
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
* $Log: /DescentIII/Main/win32/wincon.cpp $
|
||
|
*
|
||
|
* 11 4/07/99 10:56a Matt
|
||
|
* Fixed compile warning.
|
||
|
*
|
||
|
* 10 3/24/99 3:54p Jeff
|
||
|
* handle backspaces in the Printf
|
||
|
*
|
||
|
* 9 11/01/98 1:58a Jeff
|
||
|
* converted the vsprintf calls to use the Pvsprintf, which is a safe
|
||
|
* vsprintf, no buffer overflows allowed
|
||
|
*
|
||
|
* 8 10/30/98 5:52p Jeff
|
||
|
* implemented up arrow for last command, and esc to clear the line
|
||
|
*
|
||
|
* 7 10/24/98 2:18p Samir
|
||
|
* make close box inactive.
|
||
|
*
|
||
|
* 6 10/21/98 4:49p Jeff
|
||
|
* filter garbage out of strings to console
|
||
|
*
|
||
|
* 5 10/02/98 11:15a Jeff
|
||
|
* added HBITMAP, HFONT and HBRUSH type casts where needed to satisfy the
|
||
|
* compiler
|
||
|
*
|
||
|
* 4 9/16/98 6:39p Samir
|
||
|
* make sure window isn't off screen.
|
||
|
*
|
||
|
* 3 9/16/98 6:24p Samir
|
||
|
* slightly improved.
|
||
|
*
|
||
|
* 2 9/16/98 5:02p Samir
|
||
|
* reimplemented X style console.
|
||
|
*
|
||
|
* 1 9/14/98 4:02p Samir
|
||
|
* new console library.
|
||
|
*
|
||
|
* $NoKeywords: $
|
||
|
*/
|
||
|
|
||
|
#include "DDAccess.h"
|
||
|
#include "Application.h"
|
||
|
#include "AppConsole.h"
|
||
|
#include "TaskSystem.h"
|
||
|
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#include "pstring.h"
|
||
|
#include <windows.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <string.h>
|
||
|
#include <process.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#define CON_SCROLL_ROWS 25
|
||
|
#define CON_SCROLL_COLS 80
|
||
|
|
||
|
|
||
|
static bool Con_init = false;
|
||
|
static bool Con_newline = false;
|
||
|
static char *Con_buffer = NULL;
|
||
|
static int Con_row, Con_col;
|
||
|
static char Con_read_buf[CON_SCROLL_COLS+4];
|
||
|
static char Con_inp_buf[CON_SCROLL_COLS+4], Con_inp_pos=0;
|
||
|
static char Con_last_command[CON_MAX_STRINGLEN];
|
||
|
static int Con_ch_w, Con_ch_h;
|
||
|
static HWND hConWnd = NULL;
|
||
|
|
||
|
void con_Create(HWND hWnd, LPCREATESTRUCT lpcs);
|
||
|
void con_Paint(HWND hWnd);
|
||
|
void con_Destroy(HWND hWnd);
|
||
|
void con_Puts(const char *str);
|
||
|
void con_Scroll();
|
||
|
int con_KeyDown(HWND hWnd, UINT vkey);
|
||
|
int con_Char(HWND hWnd, UINT vkey);
|
||
|
|
||
|
|
||
|
void con_Printf(const char *fmt, ...)
|
||
|
{
|
||
|
char buf[CON_MAX_STRINGLEN];
|
||
|
va_list args;
|
||
|
|
||
|
// filter out messages
|
||
|
va_start(args, fmt );
|
||
|
Pvsprintf(buf,CON_MAX_STRINGLEN,fmt,args);
|
||
|
|
||
|
int len = strlen(buf);
|
||
|
if(len >= CON_MAX_STRINGLEN )
|
||
|
{
|
||
|
//we overflowed our buffer!!!
|
||
|
//we need to do some sort of error here!!!!
|
||
|
buf[CON_MAX_STRINGLEN-1] = '\0';
|
||
|
}
|
||
|
|
||
|
// filter out unprintable characters
|
||
|
char *p,*fp,filter_buf[CON_MAX_STRINGLEN];
|
||
|
p = buf;
|
||
|
fp = filter_buf;
|
||
|
|
||
|
while( *p )
|
||
|
{
|
||
|
if( *p == 0x01 )
|
||
|
{
|
||
|
//this is a color, skip the next 3
|
||
|
p+=4;
|
||
|
}else
|
||
|
{
|
||
|
if( isalnum (*p) || ispunct(*p) || (*p==' ') || (*p=='\n') || (*p=='\r') || (*p=='\b'))
|
||
|
{
|
||
|
*fp = *p;
|
||
|
fp++;
|
||
|
}
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
*fp = '\0';
|
||
|
|
||
|
con_Puts(filter_buf);
|
||
|
|
||
|
if (hConWnd) {
|
||
|
InvalidateRect(hConWnd, NULL, TRUE);
|
||
|
UpdateWindow(hConWnd);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
bool con_Input(char *buf, int buflen)
|
||
|
{
|
||
|
if (Con_read_buf[0]) {
|
||
|
strncpy(buf, Con_read_buf, buflen-1);
|
||
|
buf[buflen-1] = 0;
|
||
|
Con_read_buf[0] = 0;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
|
||
|
void con_Defer()
|
||
|
{
|
||
|
if (Con_newline) {
|
||
|
Con_newline = false;
|
||
|
con_Puts("%");
|
||
|
if (hConWnd) {
|
||
|
InvalidateRect(hConWnd, NULL, TRUE);
|
||
|
UpdateWindow(hConWnd);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// console window.
|
||
|
LRESULT WINAPI MyConProc( HWND hWnd,UINT msg,UINT wParam,LPARAM lParam)
|
||
|
{
|
||
|
HDC hdc;
|
||
|
|
||
|
switch (msg)
|
||
|
{
|
||
|
case WM_CREATE:
|
||
|
{
|
||
|
LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
|
||
|
con_Create(hWnd, lpcs);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WM_PAINT:
|
||
|
con_Paint(hWnd);
|
||
|
break;
|
||
|
|
||
|
case WM_SYSCOMMAND:
|
||
|
if (wParam == SC_CLOSE) {
|
||
|
return 0;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case WM_SETFOCUS:
|
||
|
{
|
||
|
// The window has the input focus. Load the
|
||
|
// application-defined caret resource.
|
||
|
HFONT oldfont;
|
||
|
|
||
|
hdc = GetDC(hWnd);
|
||
|
|
||
|
oldfont = (HFONT)SelectObject(hdc, (HFONT)GetStockObject(ANSI_FIXED_FONT));
|
||
|
SelectObject(hdc, oldfont);
|
||
|
CreateCaret(hWnd, NULL, Con_ch_w, Con_ch_h);
|
||
|
SetCaretPos(Con_col * Con_ch_w, Con_row * Con_ch_h);
|
||
|
ShowCaret(hWnd);
|
||
|
|
||
|
ReleaseDC(hWnd, hdc);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case WM_KILLFOCUS:
|
||
|
// The window is losing the input focus,
|
||
|
// so destroy the caret.
|
||
|
DestroyCaret();
|
||
|
break;
|
||
|
|
||
|
case WM_KEYDOWN:
|
||
|
return con_KeyDown(hWnd, wParam);
|
||
|
|
||
|
case WM_CHAR:
|
||
|
return con_Char(hWnd, wParam);
|
||
|
}
|
||
|
|
||
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
||
|
}
|
||
|
|
||
|
|
||
|
// console window helper functions
|
||
|
void con_Create(HWND hWnd, LPCREATESTRUCT lpcs)
|
||
|
{
|
||
|
oeWin32Application *app = (oeWin32Application *)lpcs->lpCreateParams;
|
||
|
HDC hdc;
|
||
|
HFONT oldfont;
|
||
|
RECT rect;
|
||
|
TEXTMETRIC tm;
|
||
|
|
||
|
// create console region
|
||
|
Con_row = 0;
|
||
|
Con_col = 0;
|
||
|
Con_buffer = new char[CON_SCROLL_ROWS * (CON_SCROLL_COLS+1)];
|
||
|
Con_read_buf[0] = 0;
|
||
|
Con_inp_pos = 0;
|
||
|
memset(Con_inp_buf, 0, sizeof(Con_inp_buf));
|
||
|
memset(Con_buffer, 0, CON_SCROLL_ROWS*(CON_SCROLL_COLS+1));
|
||
|
memset(Con_last_command, 0, sizeof(Con_last_command));
|
||
|
|
||
|
con_Puts("Outrage PC Console v1.0\n");
|
||
|
|
||
|
Con_newline = true;
|
||
|
|
||
|
// get font width and height
|
||
|
hdc = GetDC(hWnd);
|
||
|
oldfont = (HFONT)SelectObject(hdc, (HFONT)GetStockObject(ANSI_FIXED_FONT));
|
||
|
GetTextMetrics(hdc, &tm);
|
||
|
Con_ch_w = tm.tmMaxCharWidth;
|
||
|
Con_ch_h = tm.tmHeight;
|
||
|
rect.left = lpcs->x;
|
||
|
rect.top = lpcs->y;
|
||
|
rect.right = rect.left + Con_ch_w*CON_SCROLL_COLS;
|
||
|
rect.bottom = rect.top + Con_ch_h*CON_SCROLL_ROWS;
|
||
|
|
||
|
AdjustWindowRect(&rect, lpcs->style, FALSE);
|
||
|
MoveWindow(hWnd, lpcs->x, lpcs->y, rect.right-rect.left, rect.bottom-rect.top, TRUE);
|
||
|
|
||
|
app->m_X = lpcs->x;
|
||
|
app->m_Y = lpcs->y;
|
||
|
app->m_W = rect.right - rect.left;
|
||
|
app->m_H = rect.bottom - rect.top;
|
||
|
|
||
|
SelectObject(hdc, oldfont);
|
||
|
ReleaseDC(hWnd, hdc);
|
||
|
|
||
|
EnableMenuItem(GetSystemMenu(hWnd, FALSE), SC_CLOSE,MF_BYCOMMAND | MF_GRAYED);
|
||
|
|
||
|
hConWnd = hWnd;
|
||
|
}
|
||
|
|
||
|
|
||
|
void con_Paint(HWND hWnd)
|
||
|
{
|
||
|
PAINTSTRUCT ps;
|
||
|
HDC hdc = BeginPaint(hWnd, &ps);
|
||
|
int i;
|
||
|
HFONT hfont;
|
||
|
|
||
|
// use a fixed font.
|
||
|
hfont = (HFONT)SelectObject(hdc, (HFONT)GetStockObject(ANSI_FIXED_FONT));
|
||
|
|
||
|
// draw buffer at 0 to Con_row to end of buffer.
|
||
|
for (i = 0; i < CON_SCROLL_ROWS; i++)
|
||
|
{
|
||
|
char *ptr = &Con_buffer[i*(CON_SCROLL_COLS+1)];
|
||
|
TextOut(hdc, 0, i*Con_ch_h, ptr, strlen(ptr));
|
||
|
}
|
||
|
|
||
|
// end
|
||
|
SelectObject(hdc, hfont);
|
||
|
EndPaint(hWnd, &ps);
|
||
|
}
|
||
|
|
||
|
|
||
|
void con_Destroy(HWND hWnd)
|
||
|
{
|
||
|
if (Con_buffer)
|
||
|
delete[] Con_buffer;
|
||
|
|
||
|
hConWnd = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
void con_Puts(const char *str)
|
||
|
{
|
||
|
int i,len = strlen(str);
|
||
|
char *row = &Con_buffer[Con_row * (CON_SCROLL_COLS+1)];
|
||
|
bool endline = false;
|
||
|
|
||
|
for (i = 0; i < len; i++)
|
||
|
{
|
||
|
switch(str[i])
|
||
|
{
|
||
|
case '\n':
|
||
|
endline = true;
|
||
|
break;
|
||
|
case '\b':
|
||
|
if(Con_col>0)
|
||
|
{
|
||
|
row[Con_col] = ' ';
|
||
|
Con_col--;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
row[Con_col] = str[i];
|
||
|
Con_col++;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (Con_col == CON_SCROLL_COLS) {
|
||
|
endline = true;
|
||
|
}
|
||
|
|
||
|
if (endline) {
|
||
|
Con_row++;
|
||
|
if (Con_row == CON_SCROLL_ROWS) {
|
||
|
con_Scroll();
|
||
|
Con_row--;
|
||
|
}
|
||
|
row = &Con_buffer[Con_row * (CON_SCROLL_COLS+1)];
|
||
|
memset(row, 0, CON_SCROLL_COLS+1);
|
||
|
Con_col = 0;
|
||
|
endline = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SetCaretPos(Con_ch_w * Con_col, Con_ch_h * Con_row);
|
||
|
}
|
||
|
|
||
|
|
||
|
void con_Scroll()
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 1; i < CON_SCROLL_ROWS; i++)
|
||
|
memcpy(&Con_buffer[(i-1)*(CON_SCROLL_COLS+1)], &Con_buffer[i*(CON_SCROLL_COLS+1)], CON_SCROLL_COLS+1);
|
||
|
memset(&Con_buffer[(i-1)*(CON_SCROLL_COLS+1)], 0, CON_SCROLL_COLS+1);
|
||
|
}
|
||
|
|
||
|
|
||
|
int con_KeyDown(HWND hWnd, UINT vkey)
|
||
|
{
|
||
|
//HDC hdc;
|
||
|
int x;
|
||
|
char *ptr = &Con_buffer[Con_row * (CON_SCROLL_COLS+1)];
|
||
|
|
||
|
switch (vkey)
|
||
|
{
|
||
|
case VK_LEFT: // Left arrow
|
||
|
Con_col = max(Con_col - 1, 0);
|
||
|
Con_inp_pos = max(Con_inp_pos-1,0);
|
||
|
break;
|
||
|
|
||
|
case VK_RIGHT: // Right arrow
|
||
|
Con_col = min(Con_col+1, CON_SCROLL_COLS-1);
|
||
|
Con_inp_pos = min(Con_inp_pos+1, CON_SCROLL_COLS-1);
|
||
|
break;
|
||
|
|
||
|
case VK_UP: // Up arrow
|
||
|
// Replace the current buffer that is being typed with the last completed command (if there was one)
|
||
|
if(Con_last_command[0]!=0){
|
||
|
memset(Con_inp_buf, 0, sizeof(Con_inp_buf));
|
||
|
|
||
|
strcpy(Con_inp_buf,Con_last_command);
|
||
|
|
||
|
ptr[0] = '%';
|
||
|
strcpy(&ptr[1],Con_last_command); //add for %
|
||
|
|
||
|
Con_inp_pos = strlen(Con_last_command);
|
||
|
Con_col = Con_inp_pos + 1; //add for % prompt
|
||
|
|
||
|
// The application will draw outside the
|
||
|
// WM_PAINT message processing, so hide the caret.
|
||
|
HideCaret(hWnd);
|
||
|
|
||
|
// Redraw the line, adjusted for the
|
||
|
// deleted character.
|
||
|
InvalidateRect(hWnd, NULL, TRUE);
|
||
|
UpdateWindow(hWnd);
|
||
|
|
||
|
// Display the caret.
|
||
|
ShowCaret(hWnd);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case VK_DELETE: // Delete
|
||
|
// Move all the characters that followed the
|
||
|
// deleted character (on the same line) one
|
||
|
// space back (to the left) in the matrix.
|
||
|
for (x = Con_inp_pos; x < CON_SCROLL_COLS; x++)
|
||
|
Con_inp_buf[x] = Con_inp_buf[x+1];
|
||
|
|
||
|
for (x = Con_col; x < CON_SCROLL_COLS; x++)
|
||
|
ptr[x] = ptr[x+1];
|
||
|
|
||
|
// The application will draw outside the
|
||
|
// WM_PAINT message processing, so hide the caret.
|
||
|
HideCaret(hWnd);
|
||
|
|
||
|
// Redraw the line, adjusted for the
|
||
|
// deleted character.
|
||
|
InvalidateRect(hWnd, NULL, TRUE);
|
||
|
UpdateWindow(hWnd);
|
||
|
|
||
|
// Display the caret.
|
||
|
ShowCaret(hWnd);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Adjust the caret position based on the
|
||
|
// virtual-key processing.
|
||
|
SetCaretPos(Con_ch_w * Con_col, Con_ch_h * Con_row);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
int con_Char(HWND hWnd, UINT vkey)
|
||
|
{
|
||
|
HDC hdc;
|
||
|
char *ptr = &Con_buffer[Con_row * (CON_SCROLL_COLS+1)];
|
||
|
|
||
|
switch (vkey)
|
||
|
{
|
||
|
case 0x08: // Backspace
|
||
|
// Move the caret back one space, and then
|
||
|
// process this like the DEL key.
|
||
|
if (Con_inp_pos > 0)
|
||
|
Con_inp_pos--;
|
||
|
|
||
|
if (Con_col > 0) {
|
||
|
Con_col--;
|
||
|
SendMessage(hWnd, WM_KEYDOWN, VK_DELETE, 1L);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 0x0D: // Carriage return
|
||
|
{
|
||
|
// Go to the beginning of the next line.
|
||
|
// The bottom line wraps around to the top.
|
||
|
strcpy(Con_read_buf, Con_inp_buf);
|
||
|
Con_col = 0;
|
||
|
Con_row++;
|
||
|
if (Con_row == CON_SCROLL_ROWS) {
|
||
|
con_Scroll();
|
||
|
Con_row--;
|
||
|
}
|
||
|
ptr = &Con_buffer[Con_row * (CON_SCROLL_COLS+1)];
|
||
|
memset(ptr, 0, CON_SCROLL_COLS+1);
|
||
|
|
||
|
//only save the buffer if there is text in the buffer
|
||
|
char *p = Con_inp_buf;
|
||
|
while( *p ){
|
||
|
if(isalnum(*p)){
|
||
|
strcpy(Con_last_command,Con_inp_buf);
|
||
|
break;
|
||
|
}
|
||
|
p++;
|
||
|
}
|
||
|
|
||
|
memset(Con_inp_buf, 0, sizeof(Con_inp_buf));
|
||
|
Con_inp_pos = 0;
|
||
|
// con_Printf("Command is %s.\n", Con_read_buf);
|
||
|
Con_newline = true;
|
||
|
}break;
|
||
|
|
||
|
case 0x1B: // Escape
|
||
|
{
|
||
|
memset(Con_inp_buf, 0, sizeof(Con_inp_buf));
|
||
|
memset(ptr, 0, CON_SCROLL_COLS+1);
|
||
|
|
||
|
ptr[0] = '%';
|
||
|
|
||
|
Con_inp_pos = 0;
|
||
|
Con_col = 1; //for % sign
|
||
|
|
||
|
// The application will draw outside the
|
||
|
// WM_PAINT message processing, so hide the caret.
|
||
|
HideCaret(hWnd);
|
||
|
|
||
|
// Redraw the line, adjusted for the
|
||
|
// deleted character.
|
||
|
InvalidateRect(hWnd, NULL, TRUE);
|
||
|
UpdateWindow(hWnd);
|
||
|
|
||
|
// Display the caret.
|
||
|
ShowCaret(hWnd);
|
||
|
|
||
|
}break;
|
||
|
case 0x0A: // Linefeed
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
if (Con_inp_pos < (CON_SCROLL_COLS-2)) {
|
||
|
// Add the character to the text buffer.
|
||
|
int oldcol = Con_col, oldrow = Con_row;
|
||
|
char str[2];
|
||
|
|
||
|
str[0] = (char)vkey;
|
||
|
str[1] = 0;
|
||
|
|
||
|
con_Puts(str);
|
||
|
Con_inp_buf[Con_inp_pos] = (char)vkey;
|
||
|
|
||
|
// The application will draw outside the
|
||
|
// WM_PAINT message processing, so hide the caret.
|
||
|
HideCaret(hWnd);
|
||
|
|
||
|
// Draw the character on the screen.
|
||
|
hdc = GetDC(hWnd);
|
||
|
SelectObject(hdc, GetStockObject(ANSI_FIXED_FONT));
|
||
|
TextOut(hdc, Con_ch_w*oldcol, Con_ch_h*oldrow, str, 1);
|
||
|
ReleaseDC(hWnd, hdc);
|
||
|
|
||
|
// Display the caret.
|
||
|
ShowCaret(hWnd);
|
||
|
Con_inp_pos++;
|
||
|
}
|
||
|
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
SetCaretPos(Con_col*Con_ch_w, Con_row*Con_ch_h);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|