conproc.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // conproc.c
  16. #include <windows.h>
  17. #include "conproc.h"
  18. #include "quakedef.h"
  19. HANDLE heventDone;
  20. HANDLE hfileBuffer;
  21. HANDLE heventChildSend;
  22. HANDLE heventParentSend;
  23. HANDLE hStdout;
  24. HANDLE hStdin;
  25. DWORD RequestProc (DWORD dwNichts);
  26. LPVOID GetMappedBuffer (HANDLE hfileBuffer);
  27. void ReleaseMappedBuffer (LPVOID pBuffer);
  28. BOOL GetScreenBufferLines (int *piLines);
  29. BOOL SetScreenBufferLines (int iLines);
  30. BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine);
  31. BOOL WriteText (LPCTSTR szText);
  32. int CharToCode (char c);
  33. BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy);
  34. void InitConProc (HANDLE hFile, HANDLE heventParent, HANDLE heventChild)
  35. {
  36. DWORD dwID;
  37. CONSOLE_SCREEN_BUFFER_INFO info;
  38. int wheight, wwidth;
  39. // ignore if we don't have all the events.
  40. if (!hFile || !heventParent || !heventChild)
  41. return;
  42. hfileBuffer = hFile;
  43. heventParentSend = heventParent;
  44. heventChildSend = heventChild;
  45. // so we'll know when to go away.
  46. heventDone = CreateEvent (NULL, FALSE, FALSE, NULL);
  47. if (!heventDone)
  48. {
  49. Con_SafePrintf ("Couldn't create heventDone\n");
  50. return;
  51. }
  52. if (!CreateThread (NULL,
  53. 0,
  54. (LPTHREAD_START_ROUTINE) RequestProc,
  55. 0,
  56. 0,
  57. &dwID))
  58. {
  59. CloseHandle (heventDone);
  60. Con_SafePrintf ("Couldn't create QHOST thread\n");
  61. return;
  62. }
  63. // save off the input/output handles.
  64. hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
  65. hStdin = GetStdHandle (STD_INPUT_HANDLE);
  66. // force 80 character width, at least 25 character height
  67. SetConsoleCXCY (hStdout, 80, 25);
  68. }
  69. void DeinitConProc (void)
  70. {
  71. if (heventDone)
  72. SetEvent (heventDone);
  73. }
  74. DWORD RequestProc (DWORD dwNichts)
  75. {
  76. int *pBuffer;
  77. DWORD dwRet;
  78. HANDLE heventWait[2];
  79. int iBeginLine, iEndLine;
  80. heventWait[0] = heventParentSend;
  81. heventWait[1] = heventDone;
  82. while (1)
  83. {
  84. dwRet = WaitForMultipleObjects (2, heventWait, FALSE, INFINITE);
  85. // heventDone fired, so we're exiting.
  86. if (dwRet == WAIT_OBJECT_0 + 1)
  87. break;
  88. pBuffer = (int *) GetMappedBuffer (hfileBuffer);
  89. // hfileBuffer is invalid. Just leave.
  90. if (!pBuffer)
  91. {
  92. Con_SafePrintf ("Invalid hfileBuffer\n");
  93. break;
  94. }
  95. switch (pBuffer[0])
  96. {
  97. case CCOM_WRITE_TEXT:
  98. // Param1 : Text
  99. pBuffer[0] = WriteText ((LPCTSTR) (pBuffer + 1));
  100. break;
  101. case CCOM_GET_TEXT:
  102. // Param1 : Begin line
  103. // Param2 : End line
  104. iBeginLine = pBuffer[1];
  105. iEndLine = pBuffer[2];
  106. pBuffer[0] = ReadText ((LPTSTR) (pBuffer + 1), iBeginLine,
  107. iEndLine);
  108. break;
  109. case CCOM_GET_SCR_LINES:
  110. // No params
  111. pBuffer[0] = GetScreenBufferLines (&pBuffer[1]);
  112. break;
  113. case CCOM_SET_SCR_LINES:
  114. // Param1 : Number of lines
  115. pBuffer[0] = SetScreenBufferLines (pBuffer[1]);
  116. break;
  117. }
  118. ReleaseMappedBuffer (pBuffer);
  119. SetEvent (heventChildSend);
  120. }
  121. return 0;
  122. }
  123. LPVOID GetMappedBuffer (HANDLE hfileBuffer)
  124. {
  125. LPVOID pBuffer;
  126. pBuffer = MapViewOfFile (hfileBuffer,
  127. FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
  128. return pBuffer;
  129. }
  130. void ReleaseMappedBuffer (LPVOID pBuffer)
  131. {
  132. UnmapViewOfFile (pBuffer);
  133. }
  134. BOOL GetScreenBufferLines (int *piLines)
  135. {
  136. CONSOLE_SCREEN_BUFFER_INFO info;
  137. BOOL bRet;
  138. bRet = GetConsoleScreenBufferInfo (hStdout, &info);
  139. if (bRet)
  140. *piLines = info.dwSize.Y;
  141. return bRet;
  142. }
  143. BOOL SetScreenBufferLines (int iLines)
  144. {
  145. return SetConsoleCXCY (hStdout, 80, iLines);
  146. }
  147. BOOL ReadText (LPTSTR pszText, int iBeginLine, int iEndLine)
  148. {
  149. COORD coord;
  150. DWORD dwRead;
  151. BOOL bRet;
  152. coord.X = 0;
  153. coord.Y = iBeginLine;
  154. bRet = ReadConsoleOutputCharacter(
  155. hStdout,
  156. pszText,
  157. 80 * (iEndLine - iBeginLine + 1),
  158. coord,
  159. &dwRead);
  160. // Make sure it's null terminated.
  161. if (bRet)
  162. pszText[dwRead] = '\0';
  163. return bRet;
  164. }
  165. BOOL WriteText (LPCTSTR szText)
  166. {
  167. DWORD dwWritten;
  168. INPUT_RECORD rec;
  169. char upper, *sz;
  170. sz = (LPTSTR) szText;
  171. while (*sz)
  172. {
  173. // 13 is the code for a carriage return (\n) instead of 10.
  174. if (*sz == 10)
  175. *sz = 13;
  176. upper = toupper(*sz);
  177. rec.EventType = KEY_EVENT;
  178. rec.Event.KeyEvent.bKeyDown = TRUE;
  179. rec.Event.KeyEvent.wRepeatCount = 1;
  180. rec.Event.KeyEvent.wVirtualKeyCode = upper;
  181. rec.Event.KeyEvent.wVirtualScanCode = CharToCode (*sz);
  182. rec.Event.KeyEvent.uChar.AsciiChar = *sz;
  183. rec.Event.KeyEvent.uChar.UnicodeChar = *sz;
  184. rec.Event.KeyEvent.dwControlKeyState = isupper(*sz) ? 0x80 : 0x0;
  185. WriteConsoleInput(
  186. hStdin,
  187. &rec,
  188. 1,
  189. &dwWritten);
  190. rec.Event.KeyEvent.bKeyDown = FALSE;
  191. WriteConsoleInput(
  192. hStdin,
  193. &rec,
  194. 1,
  195. &dwWritten);
  196. sz++;
  197. }
  198. return TRUE;
  199. }
  200. int CharToCode (char c)
  201. {
  202. char upper;
  203. upper = toupper(c);
  204. switch (c)
  205. {
  206. case 13:
  207. return 28;
  208. default:
  209. break;
  210. }
  211. if (isalpha(c))
  212. return (30 + upper - 65);
  213. if (isdigit(c))
  214. return (1 + upper - 47);
  215. return c;
  216. }
  217. BOOL SetConsoleCXCY(HANDLE hStdout, int cx, int cy)
  218. {
  219. CONSOLE_SCREEN_BUFFER_INFO info;
  220. COORD coordMax;
  221. coordMax = GetLargestConsoleWindowSize(hStdout);
  222. if (cy > coordMax.Y)
  223. cy = coordMax.Y;
  224. if (cx > coordMax.X)
  225. cx = coordMax.X;
  226. if (!GetConsoleScreenBufferInfo(hStdout, &info))
  227. return FALSE;
  228. // height
  229. info.srWindow.Left = 0;
  230. info.srWindow.Right = info.dwSize.X - 1;
  231. info.srWindow.Top = 0;
  232. info.srWindow.Bottom = cy - 1;
  233. if (cy < info.dwSize.Y)
  234. {
  235. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  236. return FALSE;
  237. info.dwSize.Y = cy;
  238. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  239. return FALSE;
  240. }
  241. else if (cy > info.dwSize.Y)
  242. {
  243. info.dwSize.Y = cy;
  244. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  245. return FALSE;
  246. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  247. return FALSE;
  248. }
  249. if (!GetConsoleScreenBufferInfo(hStdout, &info))
  250. return FALSE;
  251. // width
  252. info.srWindow.Left = 0;
  253. info.srWindow.Right = cx - 1;
  254. info.srWindow.Top = 0;
  255. info.srWindow.Bottom = info.dwSize.Y - 1;
  256. if (cx < info.dwSize.X)
  257. {
  258. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  259. return FALSE;
  260. info.dwSize.X = cx;
  261. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  262. return FALSE;
  263. }
  264. else if (cx > info.dwSize.X)
  265. {
  266. info.dwSize.X = cx;
  267. if (!SetConsoleScreenBufferSize(hStdout, info.dwSize))
  268. return FALSE;
  269. if (!SetConsoleWindowInfo(hStdout, TRUE, &info.srWindow))
  270. return FALSE;
  271. }
  272. return TRUE;
  273. }