Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

conproc.c (8224B)


      1 /*
      2 Copyright (C) 1997-2001 Id Software, Inc.
      3 
      4 This program is free software; you can redistribute it and/or
      5 modify it under the terms of the GNU General Public License
      6 as published by the Free Software Foundation; either version 2
      7 of the License, or (at your option) any later version.
      8 
      9 This program is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
     12 
     13 See the 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, write to the Free Software
     17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     18 
     19 */
     20 // conproc.c -- support for qhost
     21 #include <stdio.h>
     22 #include <process.h>
     23 #include <windows.h>
     24 #include "conproc.h"
     25 
     26 #define CCOM_WRITE_TEXT		0x2
     27 // Param1 : Text
     28 
     29 #define CCOM_GET_TEXT		0x3
     30 // Param1 : Begin line
     31 // Param2 : End line
     32 
     33 #define CCOM_GET_SCR_LINES	0x4
     34 // No params
     35 
     36 #define CCOM_SET_SCR_LINES	0x5
     37 // Param1 : Number of lines
     38 
     39 
     40 HANDLE	heventDone;
     41 HANDLE	hfileBuffer;
     42 HANDLE	heventChildSend;
     43 HANDLE	heventParentSend;
     44 HANDLE	hStdout;
     45 HANDLE	hStdin;
     46 
     47 unsigned _stdcall RequestProc (void *arg);
     48 LPVOID GetMappedBuffer (HANDLE hfileBuffer);
     49 void ReleaseMappedBuffer (LPVOID pBuffer);
     50 BOOL GetScreenBufferLines (int *piLines);
     51 BOOL SetScreenBufferLines (int iLines);
     52 BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine);
     53 BOOL WriteText (LPCTSTR szText);
     54 int CharToCode (char c);
     55 BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy);
     56 
     57 int		ccom_argc;
     58 char	**ccom_argv;
     59 
     60 /*
     61 ================
     62 CCheckParm
     63 
     64 Returns the position (1 to argc-1) in the program's argument list
     65 where the given parameter apears, or 0 if not present
     66 ================
     67 */
     68 int CCheckParm (char *parm)
     69 {
     70 	int             i;
     71 	
     72 	for (i=1 ; i<ccom_argc ; i++)
     73 	{
     74 		if (!ccom_argv[i])
     75 			continue;
     76 		if (!strcmp (parm,ccom_argv[i]))
     77 			return i;
     78 	}
     79 		
     80 	return 0;
     81 }
     82 
     83 
     84 void InitConProc (int argc, char **argv)
     85 {
     86 	unsigned	threadAddr;
     87 	HANDLE		hFile;
     88 	HANDLE		heventParent;
     89 	HANDLE		heventChild;
     90 	int			t;
     91 
     92 	ccom_argc = argc;
     93 	ccom_argv = argv;
     94 
     95 // give QHOST a chance to hook into the console
     96 	if ((t = CCheckParm ("-HFILE")) > 0)
     97 	{
     98 		if (t < argc)
     99 			hFile = (HANDLE)atoi (ccom_argv[t+1]);
    100 	}
    101 		
    102 	if ((t = CCheckParm ("-HPARENT")) > 0)
    103 	{
    104 		if (t < argc)
    105 			heventParent = (HANDLE)atoi (ccom_argv[t+1]);
    106 	}
    107 		
    108 	if ((t = CCheckParm ("-HCHILD")) > 0)
    109 	{
    110 		if (t < argc)
    111 			heventChild = (HANDLE)atoi (ccom_argv[t+1]);
    112 	}
    113 
    114 
    115 // ignore if we don't have all the events.
    116 	if (!hFile || !heventParent || !heventChild)
    117 	{
    118 		printf ("Qhost not present.\n");
    119 		return;
    120 	}
    121 
    122 	printf ("Initializing for qhost.\n");
    123 
    124 	hfileBuffer = hFile;
    125 	heventParentSend = heventParent;
    126 	heventChildSend = heventChild;
    127 
    128 // so we'll know when to go away.
    129 	heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
    130 
    131 	if (!heventDone)
    132 	{
    133 		printf ("Couldn't create heventDone\n");
    134 		return;
    135 	}
    136 
    137 	if (!_beginthreadex (NULL, 0, RequestProc, NULL, 0, &threadAddr))
    138 	{
    139 		CloseHandle (heventDone);
    140 		printf ("Couldn't create QHOST thread\n");
    141 		return;
    142 	}
    143 
    144 // save off the input/output handles.
    145 	hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
    146 	hStdin = GetStdHandle (STD_INPUT_HANDLE);
    147 
    148 // force 80 character width, at least 25 character height
    149 	SetConsoleCXCY (hStdout, 80, 25);
    150 }
    151 
    152 
    153 void DeinitConProc (void)
    154 {
    155 	if (heventDone)
    156 		SetEvent (heventDone);
    157 }
    158 
    159 
    160 unsigned _stdcall RequestProc (void *arg)
    161 {
    162 	int		*pBuffer;
    163 	DWORD	dwRet;
    164 	HANDLE	heventWait[2];
    165 	int		iBeginLine, iEndLine;
    166 	
    167 	heventWait[0] = heventParentSend;
    168 	heventWait[1] = heventDone;
    169 
    170 	while (1)
    171 	{
    172 		dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
    173 
    174 	// heventDone fired, so we're exiting.
    175 		if (dwRet == WAIT_OBJECT_0 + 1)	
    176 			break;
    177 
    178 		pBuffer = (int *) GetMappedBuffer (hfileBuffer);
    179 		
    180 	// hfileBuffer is invalid.  Just leave.
    181 		if (!pBuffer)
    182 		{
    183 			printf ("Invalid hfileBuffer\n");
    184 			break;
    185 		}
    186 
    187 		switch (pBuffer[0])
    188 		{
    189 			case CCOM_WRITE_TEXT:
    190 			// Param1 : Text
    191 				pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
    192 				break;
    193 
    194 			case CCOM_GET_TEXT:
    195 			// Param1 : Begin line
    196 			// Param2 : End line
    197 				iBeginLine = pBuffer[1];
    198 				iEndLine = pBuffer[2];
    199 				pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine, 
    200 									   iEndLine);
    201 				break;
    202 
    203 			case CCOM_GET_SCR_LINES:
    204 			// No params
    205 				pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
    206 				break;
    207 
    208 			case CCOM_SET_SCR_LINES:
    209 			// Param1 : Number of lines
    210 				pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
    211 				break;
    212 		}
    213 
    214 		ReleaseMappedBuffer (pBuffer);
    215 		SetEvent (heventChildSend);
    216 	}
    217 
    218 	_endthreadex (0);
    219 	return 0;
    220 }
    221 
    222 
    223 LPVOID GetMappedBuffer (HANDLE hfileBuffer)
    224 {
    225 	LPVOID pBuffer;
    226 
    227 	pBuffer = MapViewOfFile (hfileBuffer,
    228 							FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    229 
    230 	return pBuffer;
    231 }
    232 
    233 
    234 void ReleaseMappedBuffer (LPVOID pBuffer)
    235 {
    236 	UnmapViewOfFile (pBuffer);
    237 }
    238 
    239 
    240 BOOL GetScreenBufferLines (int *piLines)
    241 {
    242 	CONSOLE_SCREEN_BUFFER_INFO	info;							  
    243 	BOOL						bRet;
    244 
    245 	bRet = GetConsoleScreenBufferInfo (hStdout, &info);
    246 		
    247 	if (bRet)
    248 		*piLines = info.dwSize.Y;
    249 
    250 	return bRet;
    251 }
    252 
    253 
    254 BOOL SetScreenBufferLines (int iLines)
    255 {
    256 
    257 	return SetConsoleCXCY (hStdout, 80, iLines);
    258 }
    259 
    260 
    261 BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
    262 {
    263 	COORD	coord;
    264 	DWORD	dwRead;
    265 	BOOL	bRet;
    266 
    267 	coord.X = 0;
    268 	coord.Y = iBeginLine;
    269 
    270 	bRet = ReadConsoleOutputCharacter(
    271 		hStdout,
    272 		pszText,
    273 		80 * (iEndLine - iBeginLine + 1),
    274 		coord,
    275 		&dwRead);
    276 
    277 	// Make sure it's null terminated.
    278 	if (bRet)
    279 		pszText[dwRead] = '\0';
    280 
    281 	return bRet;
    282 }
    283 
    284 
    285 BOOL WriteText (LPCTSTR szText)
    286 {
    287 	DWORD			dwWritten;
    288 	INPUT_RECORD	rec;
    289 	char			upper, *sz;
    290 
    291 	sz = (LPTSTR) szText;
    292 
    293 	while (*sz)
    294 	{
    295 	// 13 is the code for a carriage return (\n) instead of 10.
    296 		if (*sz == 10)
    297 			*sz = 13;
    298 
    299 		upper = toupper(*sz);
    300 
    301 		rec.EventType = KEY_EVENT;
    302 		rec.Event.KeyEvent.bKeyDown = TRUE;
    303 		rec.Event.KeyEvent.wRepeatCount = 1;
    304 		rec.Event.KeyEvent.wVirtualKeyCode = upper;
    305 		rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
    306 		rec.Event.KeyEvent.uChar.AsciiChar = *sz;
    307 		rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
    308 		rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0; 
    309 
    310 		WriteConsoleInput(
    311 			hStdin,
    312 			&rec,
    313 			1,
    314 			&dwWritten);
    315 
    316 		rec.Event.KeyEvent.bKeyDown = FALSE;
    317 
    318 		WriteConsoleInput(
    319 			hStdin,
    320 			&rec,
    321 			1,
    322 			&dwWritten);
    323 
    324 		sz++;
    325 	}
    326 
    327 	return TRUE;
    328 }
    329 
    330 
    331 int CharToCode (char c)
    332 {
    333 	char upper;
    334 		
    335 	upper = toupper(c);
    336 
    337 	switch (c)
    338 	{
    339 		case 13:
    340 			return 28;
    341 
    342 		default:
    343 			break;
    344 	}
    345 
    346 	if (isalpha(c))
    347 		return (30 + upper - 65); 
    348 
    349 	if (isdigit(c))
    350 		return (1 + upper - 47);
    351 
    352 	return c;
    353 }
    354 
    355 
    356 BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
    357 {
    358 	CONSOLE_SCREEN_BUFFER_INFO	info;
    359 	COORD						coordMax;
    360  
    361 	coordMax = GetLargestConsoleWindowSize(hStdout);
    362 
    363 	if (cy > coordMax.Y)
    364 		cy = coordMax.Y;
    365 
    366 	if (cx > coordMax.X)
    367 		cx = coordMax.X;
    368  
    369 	if (!GetConsoleScreenBufferInfo(hStdout, &info))
    370 		return FALSE;
    371  
    372 // height
    373     info.srWindow.Left = 0;         
    374     info.srWindow.Right = info.dwSize.X - 1;                
    375     info.srWindow.Top = 0;
    376     info.srWindow.Bottom = cy - 1;          
    377  
    378 	if (cy < info.dwSize.Y)
    379 	{
    380 		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
    381 			return FALSE;
    382  
    383 		info.dwSize.Y = cy;
    384  
    385 		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
    386 			return FALSE;
    387     }
    388     else if (cy > info.dwSize.Y)
    389     {
    390 		info.dwSize.Y = cy;
    391  
    392 		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
    393 			return FALSE;
    394  
    395 		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
    396 			return FALSE;
    397     }
    398  
    399 	if (!GetConsoleScreenBufferInfo(hStdout, &info))
    400 		return FALSE;
    401  
    402 // width
    403 	info.srWindow.Left = 0;         
    404 	info.srWindow.Right = cx - 1;
    405 	info.srWindow.Top = 0;
    406 	info.srWindow.Bottom = info.dwSize.Y - 1;               
    407  
    408 	if (cx < info.dwSize.X)
    409 	{
    410 		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
    411 			return FALSE;
    412  
    413 		info.dwSize.X = cx;
    414     
    415 		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
    416 			return FALSE;
    417 	}
    418 	else if (cx > info.dwSize.X)
    419 	{
    420 		info.dwSize.X = cx;
    421  
    422 		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
    423 			return FALSE;
    424  
    425 		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
    426 			return FALSE;
    427 	}
    428  
    429 	return TRUE;
    430 }
    431