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