Home | History | Annotate | Download | only in WinQuake
      1 /*
      2 Copyright (C) 1996-1997 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
     21 
     22 #include <windows.h>
     23 #include "conproc.h"
     24 #include "quakedef.h"
     25 
     26 HANDLE	heventDone;
     27 HANDLE	hfileBuffer;
     28 HANDLE	heventChildSend;
     29 HANDLE	heventParentSend;
     30 HANDLE	hStdout;
     31 HANDLE	hStdin;
     32 
     33 DWORD RequestProc (DWORD dwNichts);
     34 LPVOID GetMappedBuffer (HANDLE hfileBuffer);
     35 void ReleaseMappedBuffer (LPVOID pBuffer);
     36 BOOL GetScreenBufferLines (int *piLines);
     37 BOOL SetScreenBufferLines (int iLines);
     38 BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine);
     39 BOOL WriteText (LPCTSTR szText);
     40 int CharToCode (char c);
     41 BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy);
     42 
     43 
     44 void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild)
     45 {
     46 	DWORD	dwID;
     47 	CONSOLE_SCREEN_BUFFER_INFO	info;
     48 	int		wheight, wwidth;
     49 
     50 // ignore if we don't have all the events.
     51 	if (!hFile || !heventParent || !heventChild)
     52 		return;
     53 
     54 	hfileBuffer = hFile;
     55 	heventParentSend = heventParent;
     56 	heventChildSend = heventChild;
     57 
     58 // so we'll know when to go away.
     59 	heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
     60 
     61 	if (!heventDone)
     62 	{
     63 		Con_SafePrintf ("Couldn't create heventDone\n");
     64 		return;
     65 	}
     66 
     67 	if (!CreateThread (NULL,
     68 					   0,
     69 					   (LPTHREAD_START_ROUTINE) RequestProc,
     70 					   0,
     71 					   0,
     72 					   &dwID))
     73 	{
     74 		CloseHandle (heventDone);
     75 		Con_SafePrintf ("Couldn't create QHOST thread\n");
     76 		return;
     77 	}
     78 
     79 // save off the input/output handles.
     80 	hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
     81 	hStdin = GetStdHandle (STD_INPUT_HANDLE);
     82 
     83 // force 80 character width, at least 25 character height
     84 	SetConsoleCXCY (hStdout, 80, 25);
     85 }
     86 
     87 
     88 void DeinitConProc (void)
     89 {
     90 	if (heventDone)
     91 		SetEvent (heventDone);
     92 }
     93 
     94 
     95 DWORD RequestProc (DWORD dwNichts)
     96 {
     97 	int		*pBuffer;
     98 	DWORD	dwRet;
     99 	HANDLE	heventWait[2];
    100 	int		iBeginLine, iEndLine;
    101 
    102 	heventWait[0] = heventParentSend;
    103 	heventWait[1] = heventDone;
    104 
    105 	while (1)
    106 	{
    107 		dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
    108 
    109 	// heventDone fired, so we're exiting.
    110 		if (dwRet == WAIT_OBJECT_0 + 1)
    111 			break;
    112 
    113 		pBuffer = (int *) GetMappedBuffer (hfileBuffer);
    114 
    115 	// hfileBuffer is invalid.  Just leave.
    116 		if (!pBuffer)
    117 		{
    118 			Con_SafePrintf ("Invalid hfileBuffer\n");
    119 			break;
    120 		}
    121 
    122 		switch (pBuffer[0])
    123 		{
    124 			case CCOM_WRITE_TEXT:
    125 			// Param1 : Text
    126 				pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
    127 				break;
    128 
    129 			case CCOM_GET_TEXT:
    130 			// Param1 : Begin line
    131 			// Param2 : End line
    132 				iBeginLine = pBuffer[1];
    133 				iEndLine = pBuffer[2];
    134 				pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
    135 									   iEndLine);
    136 				break;
    137 
    138 			case CCOM_GET_SCR_LINES:
    139 			// No params
    140 				pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
    141 				break;
    142 
    143 			case CCOM_SET_SCR_LINES:
    144 			// Param1 : Number of lines
    145 				pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
    146 				break;
    147 		}
    148 
    149 		ReleaseMappedBuffer (pBuffer);
    150 		SetEvent (heventChildSend);
    151 	}
    152 
    153 	return 0;
    154 }
    155 
    156 
    157 LPVOID GetMappedBuffer (HANDLE hfileBuffer)
    158 {
    159 	LPVOID pBuffer;
    160 
    161 	pBuffer = MapViewOfFile (hfileBuffer,
    162 							FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    163 
    164 	return pBuffer;
    165 }
    166 
    167 
    168 void ReleaseMappedBuffer (LPVOID pBuffer)
    169 {
    170 	UnmapViewOfFile (pBuffer);
    171 }
    172 
    173 
    174 BOOL GetScreenBufferLines (int *piLines)
    175 {
    176 	CONSOLE_SCREEN_BUFFER_INFO	info;
    177 	BOOL						bRet;
    178 
    179 	bRet = GetConsoleScreenBufferInfo (hStdout, &info);
    180 
    181 	if (bRet)
    182 		*piLines = info.dwSize.Y;
    183 
    184 	return bRet;
    185 }
    186 
    187 
    188 BOOL SetScreenBufferLines (int iLines)
    189 {
    190 
    191 	return SetConsoleCXCY (hStdout, 80, iLines);
    192 }
    193 
    194 
    195 BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
    196 {
    197 	COORD	coord;
    198 	DWORD	dwRead;
    199 	BOOL	bRet;
    200 
    201 	coord.X = 0;
    202 	coord.Y = iBeginLine;
    203 
    204 	bRet = ReadConsoleOutputCharacter(
    205 		hStdout,
    206 		pszText,
    207 		80 * (iEndLine - iBeginLine + 1),
    208 		coord,
    209 		&dwRead);
    210 
    211 	// Make sure it's null terminated.
    212 	if (bRet)
    213 		pszText[dwRead] = '\0';
    214 
    215 	return bRet;
    216 }
    217 
    218 
    219 BOOL WriteText (LPCTSTR szText)
    220 {
    221 	DWORD			dwWritten;
    222 	INPUT_RECORD	rec;
    223 	char			upper, *sz;
    224 
    225 	sz = (LPTSTR) szText;
    226 
    227 	while (*sz)
    228 	{
    229 	// 13 is the code for a carriage return (\n) instead of 10.
    230 		if (*sz == 10)
    231 			*sz = 13;
    232 
    233 		upper = toupper(*sz);
    234 
    235 		rec.EventType = KEY_EVENT;
    236 		rec.Event.KeyEvent.bKeyDown = TRUE;
    237 		rec.Event.KeyEvent.wRepeatCount = 1;
    238 		rec.Event.KeyEvent.wVirtualKeyCode = upper;
    239 		rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
    240 		rec.Event.KeyEvent.uChar.AsciiChar = *sz;
    241 		rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
    242 		rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
    243 
    244 		WriteConsoleInput(
    245 			hStdin,
    246 			&rec,
    247 			1,
    248 			&dwWritten);
    249 
    250 		rec.Event.KeyEvent.bKeyDown = FALSE;
    251 
    252 		WriteConsoleInput(
    253 			hStdin,
    254 			&rec,
    255 			1,
    256 			&dwWritten);
    257 
    258 		sz++;
    259 	}
    260 
    261 	return TRUE;
    262 }
    263 
    264 
    265 int CharToCode (char c)
    266 {
    267 	char upper;
    268 
    269 	upper = toupper(c);
    270 
    271 	switch (c)
    272 	{
    273 		case 13:
    274 			return 28;
    275 
    276 		default:
    277 			break;
    278 	}
    279 
    280 	if (isalpha(c))
    281 		return (30 + upper - 65);
    282 
    283 	if (isdigit(c))
    284 		return (1 + upper - 47);
    285 
    286 	return c;
    287 }
    288 
    289 
    290 BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
    291 {
    292 	CONSOLE_SCREEN_BUFFER_INFO	info;
    293 	COORD						coordMax;
    294 
    295 	coordMax = GetLargestConsoleWindowSize(hStdout);
    296 
    297 	if (cy > coordMax.Y)
    298 		cy = coordMax.Y;
    299 
    300 	if (cx > coordMax.X)
    301 		cx = coordMax.X;
    302 
    303 	if (!GetConsoleScreenBufferInfo(hStdout, &info))
    304 		return FALSE;
    305 
    306 // height
    307     info.srWindow.Left = 0;
    308     info.srWindow.Right = info.dwSize.X - 1;
    309     info.srWindow.Top = 0;
    310     info.srWindow.Bottom = cy - 1;
    311 
    312 	if (cy < info.dwSize.Y)
    313 	{
    314 		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
    315 			return FALSE;
    316 
    317 		info.dwSize.Y = cy;
    318 
    319 		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
    320 			return FALSE;
    321     }
    322     else if (cy > info.dwSize.Y)
    323     {
    324 		info.dwSize.Y = cy;
    325 
    326 		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
    327 			return FALSE;
    328 
    329 		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
    330 			return FALSE;
    331     }
    332 
    333 	if (!GetConsoleScreenBufferInfo(hStdout, &info))
    334 		return FALSE;
    335 
    336 // width
    337 	info.srWindow.Left = 0;
    338 	info.srWindow.Right = cx - 1;
    339 	info.srWindow.Top = 0;
    340 	info.srWindow.Bottom = info.dwSize.Y - 1;
    341 
    342 	if (cx < info.dwSize.X)
    343 	{
    344 		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
    345 			return FALSE;
    346 
    347 		info.dwSize.X = cx;
    348 
    349 		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
    350 			return FALSE;
    351 	}
    352 	else if (cx > info.dwSize.X)
    353 	{
    354 		info.dwSize.X = cx;
    355 
    356 		if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
    357 			return FALSE;
    358 
    359 		if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
    360 			return FALSE;
    361 	}
    362 
    363 	return TRUE;
    364 }
    365 
    366