tncon.cpp
上传用户:tigerk9
上传日期:2020-03-10
资源大小:237k
文件大小:11k
源码类别:

Telnet客户端

开发平台:

Visual C++

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //Telnet Win32 : an ANSI telnet client.
  3. //Copyright (C) 1998-2000 Paul Brannan
  4. //Copyright (C) 1998 I.Ioannou
  5. //Copyright (C) 1997 Brad Johnson
  6. //
  7. //This program is free software; you can redistribute it and/or
  8. //modify it under the terms of the GNU General Public License
  9. //as published by the Free Software Foundation; either version 2
  10. //of the License, or (at your option) any later version.
  11. //
  12. //This program is distributed in the hope that it will be useful,
  13. //but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. //GNU General Public License for more details.
  16. //
  17. //You should have received a copy of the GNU General Public License
  18. //along with this program; if not, write to the Free Software
  19. //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. //
  21. //I.Ioannou
  22. //roryt@hol.gr
  23. //
  24. ///////////////////////////////////////////////////////////////////////////
  25. ///////////////////////////////////////////////////////////////////////////////
  26. //
  27. // Module: tncon.cpp
  28. //
  29. // Contents: telnet console processing
  30. //
  31. // Product: telnet
  32. //
  33. // Revisions: August 30, 1998 Paul Brannan <pbranna@clemson.edu>
  34. //            July 29, 1998 Paul Brannan
  35. //            June 15, 1998 Paul Brannan
  36. //            May 16, 1998 Paul Brannan
  37. //            5.April.1997 jbj@nounname.com
  38. //            9.Dec.1996 jbj@nounname.com
  39. //            Version 2.0
  40. //
  41. //            02.Apr.1995 igor.milavec@uni-lj.si
  42. //   Original code
  43. //
  44. ///////////////////////////////////////////////////////////////////////////////
  45. #include "tncon.h"
  46. #include "keytrans.h"
  47. #include "ttelhndl.h"
  48. #include "tconsole.h"
  49. #define KEYEVENT InputRecord[i].Event.KeyEvent
  50. // Paul Brannan 6/25/98
  51. // #ifdef __MINGW32__
  52. // #define KEYEVENT_CHAR KEYEVENT.AsciiChar
  53. // #else
  54. #define KEYEVENT_CHAR KEYEVENT.uChar.AsciiChar
  55. // #endif
  56. #define KEYEVENT_PCHAR &KEYEVENT_CHAR
  57. // This is for local echo (Paul Brannan 5/16/98)
  58. inline void DoEcho(const char *p, int l, TConsole &Console,
  59.    TNetwork &Network, NetParams *pParams) {
  60. // Pause the console (Paul Brannan 8/24/98)
  61. if(Network.get_local_echo()) {
  62. ResetEvent(pParams->hUnPause);
  63. SetEvent(pParams->hPause);
  64. while (!*pParams->bNetPaused); // Pause
  65. Console.WriteCtrlString(p, l);
  66. SetEvent(pParams->hUnPause); // Unpause
  67. }
  68. }
  69. // This is for line mode (Paul Brannan 12/31/98)
  70. static char buffer[1024];
  71. static unsigned int bufptr = 0;
  72. // Line mode -- currently uses sga/echo to determine when to enter line mode
  73. // (as in RFC 858), but correct behaviour is as described in RFC 1184.
  74. // (Paul Brannan 12/31/98)
  75. // FIX ME!!  What to do with unflushed data when we change from line mode
  76. // to character mode?
  77. inline bool DoLineModeSpecial(char keychar, TConsole &Console, TNetwork &Network,
  78.    NetParams *pParams) {
  79. if(keychar == VK_BACK) {
  80. if(bufptr) bufptr--;
  81. DoEcho("b b", 3, Console, Network, pParams);
  82. return true;
  83. } else if(keychar == VK_RETURN) {
  84. Network.WriteString(buffer, bufptr);
  85. Network.WriteString("12", 1);
  86. DoEcho("rn", 2, Console, Network, pParams);
  87. bufptr = 0;
  88. return true;
  89. }
  90. return false;
  91. }
  92. inline void DoLineMode(const char *p, int p_len, TConsole &Console,
  93.    TNetwork &Network) {
  94. if(Network.get_line_mode()) {
  95. if(bufptr < sizeof(buffer) + p_len - 1) {
  96. memcpy(buffer + bufptr, p, p_len);
  97. bufptr += p_len;
  98. } else {
  99. Console.Beep();
  100. }
  101. } else {
  102. Network.WriteString(p, p_len);
  103. }
  104. }
  105. // Paul Brannan 5/27/98
  106. // Fixed this code for use with appliation cursor keys
  107. // This should probably be optimized; it's pretty ugly as it is
  108. // Rewrite #1: now uses ClosestStateKey (Paul Brannan 12/9/98)
  109. const char *ClosestStateKey(WORD keyCode, DWORD keyState,
  110. KeyTranslator &KeyTrans) {
  111. char const *p;
  112. if((p = KeyTrans.TranslateKey(keyCode, keyState))) return p;
  113. // Check numlock and scroll lock (Paul Brannan 9/23/98)
  114. if((p = KeyTrans.TranslateKey(keyCode, keyState & ~NUMLOCK_ON))) return p;
  115. if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY
  116. & ~NUMLOCK_ON))) return p;
  117. if((p = KeyTrans.TranslateKey(keyCode, keyState & ~SCROLLLOCK_ON))) return p;
  118. if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY
  119. & ~SCROLLLOCK_ON))) return p;
  120. //  John Ioannou (roryt@hol.gr)
  121. //   Athens 31/03/97 00:25am GMT+2
  122. //   fix for win95 CAPSLOCK bug
  123. //   first check if the user has keys with capslock and then we filter it
  124. if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY))) return p;
  125. if((p = KeyTrans.TranslateKey(keyCode, keyState & ~CAPSLOCK_ON))) return p;
  126. if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY
  127. & ~CAPSLOCK_ON))) return p;
  128. return 0; // we couldn't find a suitable key translation
  129. }
  130. const char *FindClosestKey(WORD keyCode, DWORD keyState,
  131.    KeyTranslator &KeyTrans) {
  132. char const *p;
  133. // Paul Brannan 7/20/98
  134. if(ini.get_alt_erase()) {
  135. if(keyCode == VK_BACK) {
  136. keyCode = VK_DELETE;
  137. keyState |= ENHANCED_KEY;
  138. } else if(keyCode == VK_DELETE && (keyState & ENHANCED_KEY)) {
  139. keyCode = VK_BACK;
  140. keyState &= ~ENHANCED_KEY;
  141. }
  142. }
  143. DWORD ext_mode = KeyTrans.get_ext_mode();
  144. if(ext_mode) {
  145. // Not as fast as an unrolled loop, but certainly more
  146. // compact (Paul Brannan 12/9/98)
  147. for(DWORD j = ext_mode; j >= APP_KEY; j -= APP_KEY) {
  148. if((j | ext_mode) == ext_mode) {
  149. if((p = ClosestStateKey(keyCode, keyState | j,
  150. KeyTrans))) return p;
  151. }
  152. }
  153. }
  154. return ClosestStateKey(keyCode, keyState, KeyTrans);
  155. }
  156. // Paul Brannan Feb. 22, 1999
  157. int do_op(tn_ops op, TNetwork &Network, Tnclip &Clipboard) {
  158. switch(op) {
  159. case TN_ESCAPE:
  160. return TNPROMPT;
  161. case TN_SCROLLBACK:
  162. return TNSCROLLBACK;
  163. case TN_DIAL:
  164. return TNSPAWN;
  165. case TN_PASTE:
  166. if(ini.get_keyboard_paste()) Clipboard.Paste();
  167. else return 0;
  168. break;
  169. case TN_NULL:
  170. Network.WriteString("", 1);
  171. return 0;
  172. case TN_CR:
  173. Network.WriteString("r", 2); // CR must be followed by NUL
  174. return 0;
  175. case TN_CRLF:
  176. Network.WriteString("rn", 2);
  177. return 0;
  178. }
  179. return 0;
  180. }
  181. int telProcessConsole(NetParams *pParams, KeyTranslator &KeyTrans,
  182.   TConsole &Console, TNetwork &Network, TMouse &Mouse,
  183.   Tnclip &Clipboard, HANDLE hThread)
  184. {
  185. KeyDefType_const keydef;
  186. const char *p;
  187. int p_len;
  188. unsigned int i;
  189. int opval;
  190. HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
  191. SetConsoleMode(hConsole, ini.get_enable_mouse() ? ENABLE_MOUSE_INPUT : 0);
  192. const DWORD nHandle = 2;
  193. HANDLE hHandle[nHandle] = {hConsole, pParams->hExit};
  194. for (;;) {
  195. DWORD dwInput;
  196. switch (WaitForMultipleObjects(nHandle, hHandle, FALSE, INFINITE)) {
  197.         case WAIT_OBJECT_0: {
  198. // Paul Brannan 7/29/98
  199. if(ini.get_input_redir()) {
  200. char InputBuffer[10];
  201. // Correction from Joe Manns <joe.manns@ardenenginneers.com>
  202. // to fix race conditions (4/13/99)
  203. int bResult;
  204. bResult = ReadFile(hConsole, InputBuffer, 10, &dwInput, 0);
  205. if(bResult && dwInput == 0) return TNNOCON;
  206. // no key translation for redirected input
  207. Network.WriteString(InputBuffer, dwInput);
  208. break;
  209. }
  210. INPUT_RECORD InputRecord[11];
  211. if (!ReadConsoleInput(hConsole, &InputRecord[0], 10, &dwInput))
  212. return TNPROMPT;
  213. for (i = 0; (unsigned)i < dwInput; i++){
  214. switch (InputRecord[i].EventType) {
  215. case KEY_EVENT:{
  216. if (KEYEVENT.bKeyDown) {
  217. WORD  keyCode  = KEYEVENT.wVirtualKeyCode;
  218. DWORD keyState = KEYEVENT.dwControlKeyState;
  219. // Paul Brannan 5/27/98
  220. // Moved the code that was here to FindClosestKey()
  221. keydef.szKeyDef = FindClosestKey(keyCode,
  222. keyState, KeyTrans);
  223. if(keydef.szKeyDef) {
  224. if(!keydef.op->sendstr)
  225. if((opval = do_op(keydef.op->the_op, Network,
  226. Clipboard)) != 0)
  227. return opval;
  228. }
  229. if(Network.get_line_mode()) {
  230. if(DoLineModeSpecial(KEYEVENT_CHAR, Console, Network, pParams))
  231. continue;
  232. }
  233. p = keydef.szKeyDef;
  234. if (p == NULL) { // if we don't have a translator
  235. if(!KEYEVENT_CHAR) continue;
  236. p_len = 1;
  237. p = KEYEVENT_PCHAR;
  238. } else {
  239. p_len = strlen(p);
  240. }
  241. // Local echo (Paul Brannan 5/16/98)
  242. DoEcho(p, p_len, Console, Network, pParams);
  243. // Line mode (Paul Brannan 12/31/98)
  244. DoLineMode(p, p_len, Console, Network);
  245. }
  246.    }
  247. break;
  248. case MOUSE_EVENT:
  249. if(!InputRecord[i].Event.MouseEvent.dwEventFlags) {
  250. ResetEvent(pParams->hUnPause);
  251. SetEvent(pParams->hPause);
  252. while (!*pParams->bNetPaused); // thread paused
  253. // SuspendThread(hThread);
  254. // Put the mouse's X and Y coords back into the
  255. // input buffer
  256. DWORD Result;
  257. WriteConsoleInput(hConsole, &InputRecord[i], 1,
  258. &Result);
  259. Mouse.doMouse();
  260. SetEvent(pParams->hUnPause);
  261. // ResumeThread(hThread);
  262. }
  263. break;
  264. case FOCUS_EVENT:
  265. break;
  266. case WINDOW_BUFFER_SIZE_EVENT:
  267. // FIX ME!!  This should take care of the window re-sizing bug
  268. // Unfortunately, it doesn't.
  269. Console.sync();
  270. Network.do_naws(Console.GetWidth(), Console.GetHeight());
  271. break;
  272. }
  273. } // keep going until no more input
  274. break;
  275. }
  276.         default:
  277. return TNNOCON;
  278. }
  279. }
  280. }
  281. WORD scrollkeys() {
  282. HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE);
  283. INPUT_RECORD InputRecord;
  284. BOOL done = FALSE;
  285. while (!done) {
  286. DWORD dwInput;
  287. WaitForSingleObject( hConsole, INFINITE );
  288. if (!ReadConsoleInput(hConsole, &InputRecord, 1, &dwInput)){
  289. done = TRUE;
  290. continue;
  291. }
  292. if (InputRecord.EventType == KEY_EVENT &&
  293. InputRecord.Event.KeyEvent.bKeyDown ) {
  294. // Why not just return the key code?  (Paul Brannan 12/5/98)
  295. return InputRecord.Event.KeyEvent.wVirtualKeyCode;
  296. } else if(InputRecord.EventType == MOUSE_EVENT) {
  297. if(!InputRecord.Event.MouseEvent.dwEventFlags) {
  298. // Put the mouse's X and Y coords back into the input buffer
  299. WriteConsoleInput(hConsole, &InputRecord, 1, &dwInput);
  300. return SC_MOUSE;
  301. }
  302. }
  303. }
  304. return SC_ESC;
  305. }
  306. // FIX ME!!  This is more evidence that tncon.cpp ought to have class structure
  307. // (Paul Brannan 12/10/98)
  308. // Bryan Montgomery 10/14/98
  309. static TNetwork net;
  310. void setTNetwork(TNetwork tnet) {
  311. net = tnet;
  312. }
  313. // Thomas Briggs 8/17/98
  314. BOOL WINAPI ControlEventHandler(DWORD event) {
  315. switch(event) {
  316. case CTRL_BREAK_EVENT:
  317. // Bryan Montgomery 10/14/98
  318. if(ini.get_control_break_as_c()) net.WriteString("x3",1);
  319. return TRUE;
  320. default:
  321. return FALSE;
  322. }
  323. }