ReactOS  0.4.12-dev-18-gf469aca
tncon.cpp
Go to the documentation of this file.
1 //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 //
25 
27 //
28 // Module: tncon.cpp
29 //
30 // Contents: telnet console processing
31 //
32 // Product: telnet
33 //
34 // Revisions: August 30, 1998 Paul Brannan <pbranna@clemson.edu>
35 // July 29, 1998 Paul Brannan
36 // June 15, 1998 Paul Brannan
37 // May 16, 1998 Paul Brannan
38 // 5.April.1997 jbj@nounname.com
39 // 9.Dec.1996 jbj@nounname.com
40 // Version 2.0
41 //
42 // 02.Apr.1995 igor.milavec@uni-lj.si
43 // Original code
44 //
46 
47 #include "precomp.h"
48 
49 #define KEYEVENT InputRecord[i].Event.KeyEvent
50 
51 // Paul Brannan 6/25/98
52 // #ifdef __MINGW32__
53 // #define KEYEVENT_CHAR KEYEVENT.AsciiChar
54 // #else
55 #define KEYEVENT_CHAR KEYEVENT.uChar.AsciiChar
56 // #endif
57 
58 #define KEYEVENT_PCHAR &KEYEVENT_CHAR
59 
60 // This is for local echo (Paul Brannan 5/16/98)
61 inline void DoEcho(const char *p, int l, TConsole &Console,
62  TNetwork &Network, NetParams *pParams) {
63  // Pause the console (Paul Brannan 8/24/98)
64  if(Network.get_local_echo()) {
65  ResetEvent(pParams->hUnPause);
66  SetEvent(pParams->hPause);
67  while (!*pParams->bNetPaused); // Pause
68 
69  Console.WriteCtrlString(p, l);
70 
71  SetEvent(pParams->hUnPause); // Unpause
72  }
73 }
74 
75 // This is for line mode (Paul Brannan 12/31/98)
76 static char buffer[1024];
77 static unsigned int bufptr = 0;
78 
79 // Line mode -- currently uses sga/echo to determine when to enter line mode
80 // (as in RFC 858), but correct behaviour is as described in RFC 1184.
81 // (Paul Brannan 12/31/98)
82 // FIX ME!! What to do with unflushed data when we change from line mode
83 // to character mode?
84 inline bool DoLineModeSpecial(char keychar, TConsole &Console, TNetwork &Network,
85  NetParams *pParams) {
86  if(keychar == VK_BACK) {
87  if(bufptr) bufptr--;
88  DoEcho("\b \b", 3, Console, Network, pParams);
89  return true;
90  } else if(keychar == VK_RETURN) {
91  Network.WriteString(buffer, bufptr);
92  Network.WriteString("\012", 1);
93  DoEcho("\r\n", 2, Console, Network, pParams);
94  bufptr = 0;
95  return true;
96  }
97  return false;
98 }
99 
100 inline void DoLineMode(const char *p, int p_len, TConsole &Console,
101  TNetwork &Network) {
102  if(Network.get_line_mode()) {
103  if(bufptr < sizeof(buffer) + p_len - 1) {
104  memcpy(buffer + bufptr, p, p_len);
105  bufptr += p_len;
106  } else {
107  Console.Beep();
108  }
109  } else {
110  Network.WriteString(p, p_len);
111  }
112 }
113 
114 // Paul Brannan 5/27/98
115 // Fixed this code for use with appliation cursor keys
116 // This should probably be optimized; it's pretty ugly as it is
117 // Rewrite #1: now uses ClosestStateKey (Paul Brannan 12/9/98)
118 const char *ClosestStateKey(WORD keyCode, DWORD keyState,
119  KeyTranslator &KeyTrans) {
120  char const *p;
121 
122  if((p = KeyTrans.TranslateKey(keyCode, keyState))) return p;
123 
124  // Check numlock and scroll lock (Paul Brannan 9/23/98)
125  if((p = KeyTrans.TranslateKey(keyCode, keyState & ~NUMLOCK_ON))) return p;
126  if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY
127  & ~NUMLOCK_ON))) return p;
128  if((p = KeyTrans.TranslateKey(keyCode, keyState & ~SCROLLLOCK_ON))) return p;
129  if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY
130  & ~SCROLLLOCK_ON))) return p;
131 
132  // John Ioannou (roryt@hol.gr)
133  // Athens 31/03/97 00:25am GMT+2
134  // fix for win95 CAPSLOCK bug
135  // first check if the user has keys with capslock and then we filter it
136  if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY))) return p;
137  if((p = KeyTrans.TranslateKey(keyCode, keyState & ~CAPSLOCK_ON))) return p;
138  if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY
139  & ~CAPSLOCK_ON))) return p;
140 
141  return 0; // we couldn't find a suitable key translation
142 }
143 
144 const char *FindClosestKey(WORD keyCode, DWORD keyState,
145  KeyTranslator &KeyTrans) {
146  char const *p;
147 
148  // Paul Brannan 7/20/98
149  if(ini.get_alt_erase()) {
150  if(keyCode == VK_BACK) {
151  keyCode = VK_DELETE;
152  keyState |= ENHANCED_KEY;
153  } else if(keyCode == VK_DELETE && (keyState & ENHANCED_KEY)) {
154  keyCode = VK_BACK;
155  keyState &= ~ENHANCED_KEY;
156  }
157  }
158 
159  DWORD ext_mode = KeyTrans.get_ext_mode();
160  if(ext_mode) {
161  // Not as fast as an unrolled loop, but certainly more
162  // compact (Paul Brannan 12/9/98)
163  for(DWORD j = ext_mode; j >= APP_KEY; j -= APP_KEY) {
164  if((j | ext_mode) == ext_mode) {
165  if((p = ClosestStateKey(keyCode, keyState | j,
166  KeyTrans))) return p;
167  }
168  }
169  }
170  return ClosestStateKey(keyCode, keyState, KeyTrans);
171 }
172 
173 // Paul Brannan Feb. 22, 1999
174 int do_op(tn_ops op, TNetwork &Network, Tnclip &Clipboard) {
175  switch(op) {
176  case TN_ESCAPE:
177  return TNPROMPT;
178  case TN_SCROLLBACK:
179  return TNSCROLLBACK;
180  case TN_DIAL:
181  return TNSPAWN;
182  case TN_PASTE:
183  if(ini.get_keyboard_paste()) Clipboard.Paste();
184  else return 0;
185  break;
186  case TN_NULL:
187  Network.WriteString("", 1);
188  return 0;
189  case TN_CR:
190  Network.WriteString("\r", 2); // CR must be followed by NUL
191  return 0;
192  case TN_CRLF:
193  Network.WriteString("\r\n", 2);
194  return 0;
195  }
196  return 0;
197 }
198 
199 int telProcessConsole(NetParams *pParams, KeyTranslator &KeyTrans,
201  Tnclip &Clipboard, HANDLE hThread)
202 {
203  KeyDefType_const keydef;
204  const char *p;
205  int p_len;
206  unsigned int i;
207  int opval;
209 
211 
212  const DWORD nHandle = 2;
213  HANDLE hHandle[nHandle] = {hConsole, pParams->hExit};
214 
215  for (;;) {
216  DWORD dwInput;
217  switch (WaitForMultipleObjects(nHandle, hHandle, FALSE, INFINITE)) {
218  case WAIT_OBJECT_0: {
219 
220  // Paul Brannan 7/29/98
221  if(ini.get_input_redir()) {
222  char InputBuffer[10];
223 
224  // Correction from Joe Manns <joe.manns@ardenenginneers.com>
225  // to fix race conditions (4/13/99)
226  int bResult;
227  bResult = ReadFile(hConsole, InputBuffer, 10, &dwInput, 0);
228  if(bResult && dwInput == 0) return TNNOCON;
229 
230  // no key translation for redirected input
231  Network.WriteString(InputBuffer, dwInput);
232  break;
233  }
234 
235  INPUT_RECORD InputRecord[11];
236  if (!ReadConsoleInput(hConsole, &InputRecord[0], 10, &dwInput))
237  return TNPROMPT;
238 
239  for (i = 0; (unsigned)i < dwInput; i++){
240  switch (InputRecord[i].EventType) {
241  case KEY_EVENT:{
242  if (KEYEVENT.bKeyDown) {
243 
244  WORD keyCode = KEYEVENT.wVirtualKeyCode;
245  DWORD keyState = KEYEVENT.dwControlKeyState;
246 
247  // Paul Brannan 5/27/98
248  // Moved the code that was here to FindClosestKey()
249  keydef.szKeyDef = FindClosestKey(keyCode,
250  keyState, KeyTrans);
251 
252  if(keydef.szKeyDef) {
253  if(!keydef.op->sendstr)
254  if((opval = do_op(keydef.op->the_op, Network,
255  Clipboard)) != 0)
256  return opval;
257  }
258 
259  if(Network.get_line_mode()) {
260  if(DoLineModeSpecial(KEYEVENT_CHAR, Console, Network, pParams))
261  continue;
262  }
263 
264  p = keydef.szKeyDef;
265  if (p == NULL) { // if we don't have a translator
266  if(!KEYEVENT_CHAR) continue;
267  p_len = 1;
268  p = KEYEVENT_PCHAR;
269  } else {
270  p_len = strlen(p);
271  }
272 
273  // Local echo (Paul Brannan 5/16/98)
274  DoEcho(p, p_len, Console, Network, pParams);
275  // Line mode (Paul Brannan 12/31/98)
276  DoLineMode(p, p_len, Console, Network);
277  }
278  }
279  break;
280 
281  case MOUSE_EVENT:
282  if(!InputRecord[i].Event.MouseEvent.dwEventFlags) {
283  ResetEvent(pParams->hUnPause);
284  SetEvent(pParams->hPause);
285  while (!*pParams->bNetPaused); // thread paused
286  // SuspendThread(hThread);
287 
288  // Put the mouse's X and Y coords back into the
289  // input buffer
290  DWORD Result;
291  WriteConsoleInput(hConsole, &InputRecord[i], 1,
292  &Result);
293 
294  Mouse.doMouse();
295 
296  SetEvent(pParams->hUnPause);
297  // ResumeThread(hThread);
298  }
299  break;
300 
301  case FOCUS_EVENT:
302  break;
304  // FIX ME!! This should take care of the window re-sizing bug
305  // Unfortunately, it doesn't.
306  Console.sync();
307  Network.do_naws(Console.GetWidth(), Console.GetHeight());
308  break;
309  }
310 
311  } // keep going until no more input
312  break;
313  }
314  default:
315  return TNNOCON;
316  }
317  }
318 }
319 
322  INPUT_RECORD InputRecord;
323  BOOL done = FALSE;
324 
325  while (!done) {
326  DWORD dwInput;
327  WaitForSingleObject( hConsole, INFINITE );
328  if (!ReadConsoleInput(hConsole, &InputRecord, 1, &dwInput)){
329  done = TRUE;
330  continue;
331  }
332  if (InputRecord.EventType == KEY_EVENT &&
333  InputRecord.Event.KeyEvent.bKeyDown ) {
334  // Why not just return the key code? (Paul Brannan 12/5/98)
335  return InputRecord.Event.KeyEvent.wVirtualKeyCode;
336  } else if(InputRecord.EventType == MOUSE_EVENT) {
337  if(!InputRecord.Event.MouseEvent.dwEventFlags) {
338  // Put the mouse's X and Y coords back into the input buffer
339  WriteConsoleInput(hConsole, &InputRecord, 1, &dwInput);
340  return SC_MOUSE;
341  }
342  }
343  }
344  return SC_ESC;
345 }
346 
347 // FIX ME!! This is more evidence that tncon.cpp ought to have class structure
348 // (Paul Brannan 12/10/98)
349 
350 // Bryan Montgomery 10/14/98
351 static TNetwork net;
352 void setTNetwork(TNetwork tnet) {
353  net = tnet;
354 }
355 
356 // Thomas Briggs 8/17/98
358  switch(event) {
359  case CTRL_BREAK_EVENT:
360  // Bryan Montgomery 10/14/98
361  if(ini.get_control_break_as_c()) net.WriteString("\x3",1);
362  return TRUE;
363  default:
364  return FALSE;
365  }
366 }
bool get_keyboard_paste() const
Definition: tnconfig.h:86
#define SCROLLLOCK_ON
Definition: wincon.h:137
void Paste()
Definition: tnclip.cpp:48
bool get_alt_erase() const
Definition: tnconfig.h:85
const optype * op
Definition: tkeydef.h:33
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
void DoEcho(const char *p, int l, TConsole &Console, TNetwork &Network, NetParams *pParams)
Definition: tncon.cpp:61
#define TRUE
Definition: types.h:120
#define CTRL_BREAK_EVENT
Definition: wincon.h:66
DWORD dwEventFlags
Definition: wincon.h:245
static unsigned int bufptr
Definition: tncon.cpp:77
void DoLineMode(const char *p, int p_len, TConsole &Console, TNetwork &Network)
Definition: tncon.cpp:100
#define APP_KEY
Definition: keytrans.h:41
HANDLE hUnPause
Definition: tparams.h:7
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define WINDOW_BUFFER_SIZE_EVENT
Definition: wincon.h:124
void sync()
Definition: tconsole.cpp:109
#define WriteConsoleInput
Definition: wincon.h:773
unsigned long WriteCtrlString(const char *pszString, unsigned long cbString)
Definition: tconsole.cpp:542
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:679
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:152
GLuint buffer
Definition: glext.h:5915
WORD scrollkeys()
Definition: tncon.cpp:320
tn_ops the_op
Definition: tkeydef.h:23
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
#define VK_RETURN
Definition: winuser.h:2155
CHAR InputBuffer[80]
Definition: conmgr.c:33
volatile int * bNetPaused
Definition: tparams.h:8
WORD wVirtualKeyCode
Definition: wincon.h:227
#define KEYEVENT_PCHAR
Definition: tncon.cpp:58
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
const char * ClosestStateKey(WORD keyCode, DWORD keyState, KeyTranslator &KeyTrans)
Definition: tncon.cpp:118
GLenum GLclampf GLint i
Definition: glfuncs.h:14
bool get_control_break_as_c() const
Definition: tnconfig.h:61
DWORD get_ext_mode()
Definition: keytrans.h:77
UINT op
Definition: effect.c:223
#define ReadConsoleInput
Definition: wincon.h:766
BOOL get_local_echo()
Definition: tnetwork.h:40
BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode)
Definition: console.c:1608
#define KEY_EVENT
Definition: wincon.h:122
tn_ops
Definition: tkeydef.h:19
const char * szKeyDef
Definition: tkeydef.h:32
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
Definition: tncon.h:15
#define FOCUS_EVENT
Definition: wincon.h:126
#define STD_INPUT_HANDLE
Definition: winbase.h:264
Definition: tnclip.h:6
#define VK_DELETE
Definition: winuser.h:2187
void setTNetwork(TNetwork tnet)
Definition: tncon.cpp:352
r l[0]
Definition: byte_order.h:167
BOOL WINAPI ControlEventHandler(DWORD event)
Definition: tncon.cpp:357
TConfig ini
Definition: tnconfig.cpp:45
int WriteString(const char *str, const int length)
Definition: tnetwork.cpp:53
unsigned int BOOL
Definition: ntddk_ex.h:94
#define WAIT_OBJECT_0
Definition: winbase.h:387
#define KEYEVENT_CHAR
Definition: tncon.cpp:55
#define ENHANCED_KEY
Definition: wincon.h:139
#define KEYEVENT
Definition: tncon.cpp:49
#define MOUSE_EVENT
Definition: wincon.h:123
KEY_EVENT_RECORD KeyEvent
Definition: wincon.h:263
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
void doMouse()
Definition: tmouse.cpp:141
#define ENABLE_MOUSE_INPUT
Definition: wincon.h:79
int get_input_redir() const
Definition: tnconfig.h:42
int GetWidth()
Definition: tconsole.h:81
Definition: tkeydef.h:19
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
Definition: tncon.h:11
struct _cl_event * event
Definition: glext.h:7739
#define VK_BACK
Definition: winuser.h:2152
#define WINAPI
Definition: msvc.h:20
static TNetwork net
Definition: tncon.cpp:351
bool get_enable_mouse() const
Definition: tnconfig.h:79
Definition: tncon.h:18
BOOL get_line_mode()
Definition: tnetwork.h:43
bool DoLineModeSpecial(char keychar, TConsole &Console, TNetwork &Network, NetParams *pParams)
Definition: tncon.cpp:84
HANDLE hExit
Definition: tparams.h:6
HANDLE hThread
Definition: wizard.c:27
BOOL WINAPI DECLSPEC_HOTPATCH ResetEvent(IN HANDLE hEvent)
Definition: synch.c:660
HANDLE hPause
Definition: tparams.h:7
CConsole Console
WORD EventType
Definition: wincon.h:261
char sendstr
Definition: tkeydef.h:22
void do_naws(int width, int height)
Definition: tnetwork.cpp:81
MOUSE_EVENT_RECORD MouseEvent
Definition: wincon.h:264
int telProcessConsole(NetParams *pParams, KeyTranslator &KeyTrans, TConsole &Console, TNetwork &Network, TMouse &Mouse, Tnclip &Clipboard, HANDLE hThread)
Definition: tncon.cpp:199
_In_ ACCESS_MASK _In_opt_ POBJECT_ATTRIBUTES _In_ EVENT_TYPE EventType
Definition: exfuncs.h:165
GLfloat GLfloat p
Definition: glext.h:8902
Definition: tncon.h:10
#define INFINITE
Definition: serial.h:102
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
Definition: tmouse.h:6
Definition: tncon.h:16
const char * TranslateKey(WORD wVirtualKeyCode, DWORD dwControlKeyState)
Definition: keytrans.cpp:94
const char * FindClosestKey(WORD keyCode, DWORD keyState, KeyTranslator &KeyTrans)
Definition: tncon.cpp:144
void Beep()
Definition: tconsole.cpp:922
union _INPUT_RECORD::@3146 Event
#define NUMLOCK_ON
Definition: wincon.h:136
int do_op(tn_ops op, TNetwork &Network, Tnclip &Clipboard)
Definition: tncon.cpp:174
#define CAPSLOCK_ON
Definition: wincon.h:138
int GetHeight()
Definition: tconsole.h:82