Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 432 lines (324 sloc) 8.224 kb
372afde @tbradshaw The original Quake 2 sources as originally released under the GPL licens...
tbradshaw authored
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
Something went wrong with that request. Please try again.