Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentncon.cpp
Go to the documentation of this file.
00001 00002 //Telnet Win32 : an ANSI telnet client. 00003 //Copyright (C) 1998-2000 Paul Brannan 00004 //Copyright (C) 1998 I.Ioannou 00005 //Copyright (C) 1997 Brad Johnson 00006 // 00007 //This program is free software; you can redistribute it and/or 00008 //modify it under the terms of the GNU General Public License 00009 //as published by the Free Software Foundation; either version 2 00010 //of the License, or (at your option) any later version. 00011 // 00012 //This program is distributed in the hope that it will be useful, 00013 //but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 //GNU General Public License for more details. 00016 // 00017 //You should have received a copy of the GNU General Public License 00018 //along with this program; if not, write to the Free Software 00019 //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 // 00021 //I.Ioannou 00022 //roryt@hol.gr 00023 // 00025 00027 // 00028 // Module: tncon.cpp 00029 // 00030 // Contents: telnet console processing 00031 // 00032 // Product: telnet 00033 // 00034 // Revisions: August 30, 1998 Paul Brannan <pbranna@clemson.edu> 00035 // July 29, 1998 Paul Brannan 00036 // June 15, 1998 Paul Brannan 00037 // May 16, 1998 Paul Brannan 00038 // 5.April.1997 jbj@nounname.com 00039 // 9.Dec.1996 jbj@nounname.com 00040 // Version 2.0 00041 // 00042 // 02.Apr.1995 igor.milavec@uni-lj.si 00043 // Original code 00044 // 00046 00047 #include "precomp.h" 00048 00049 #define KEYEVENT InputRecord[i].Event.KeyEvent 00050 00051 // Paul Brannan 6/25/98 00052 // #ifdef __MINGW32__ 00053 // #define KEYEVENT_CHAR KEYEVENT.AsciiChar 00054 // #else 00055 #define KEYEVENT_CHAR KEYEVENT.uChar.AsciiChar 00056 // #endif 00057 00058 #define KEYEVENT_PCHAR &KEYEVENT_CHAR 00059 00060 // This is for local echo (Paul Brannan 5/16/98) 00061 inline void DoEcho(const char *p, int l, TConsole &Console, 00062 TNetwork &Network, NetParams *pParams) { 00063 // Pause the console (Paul Brannan 8/24/98) 00064 if(Network.get_local_echo()) { 00065 ResetEvent(pParams->hUnPause); 00066 SetEvent(pParams->hPause); 00067 while (!*pParams->bNetPaused); // Pause 00068 00069 Console.WriteCtrlString(p, l); 00070 00071 SetEvent(pParams->hUnPause); // Unpause 00072 } 00073 } 00074 00075 // This is for line mode (Paul Brannan 12/31/98) 00076 static char buffer[1024]; 00077 static unsigned int bufptr = 0; 00078 00079 // Line mode -- currently uses sga/echo to determine when to enter line mode 00080 // (as in RFC 858), but correct behaviour is as described in RFC 1184. 00081 // (Paul Brannan 12/31/98) 00082 // FIX ME!! What to do with unflushed data when we change from line mode 00083 // to character mode? 00084 inline bool DoLineModeSpecial(char keychar, TConsole &Console, TNetwork &Network, 00085 NetParams *pParams) { 00086 if(keychar == VK_BACK) { 00087 if(bufptr) bufptr--; 00088 DoEcho("\b \b", 3, Console, Network, pParams); 00089 return true; 00090 } else if(keychar == VK_RETURN) { 00091 Network.WriteString(buffer, bufptr); 00092 Network.WriteString("\012", 1); 00093 DoEcho("\r\n", 2, Console, Network, pParams); 00094 bufptr = 0; 00095 return true; 00096 } 00097 return false; 00098 } 00099 00100 inline void DoLineMode(const char *p, int p_len, TConsole &Console, 00101 TNetwork &Network) { 00102 if(Network.get_line_mode()) { 00103 if(bufptr < sizeof(buffer) + p_len - 1) { 00104 memcpy(buffer + bufptr, p, p_len); 00105 bufptr += p_len; 00106 } else { 00107 Console.Beep(); 00108 } 00109 } else { 00110 Network.WriteString(p, p_len); 00111 } 00112 } 00113 00114 // Paul Brannan 5/27/98 00115 // Fixed this code for use with appliation cursor keys 00116 // This should probably be optimized; it's pretty ugly as it is 00117 // Rewrite #1: now uses ClosestStateKey (Paul Brannan 12/9/98) 00118 const char *ClosestStateKey(WORD keyCode, DWORD keyState, 00119 KeyTranslator &KeyTrans) { 00120 char const *p; 00121 00122 if((p = KeyTrans.TranslateKey(keyCode, keyState))) return p; 00123 00124 // Check numlock and scroll lock (Paul Brannan 9/23/98) 00125 if((p = KeyTrans.TranslateKey(keyCode, keyState & ~NUMLOCK_ON))) return p; 00126 if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY 00127 & ~NUMLOCK_ON))) return p; 00128 if((p = KeyTrans.TranslateKey(keyCode, keyState & ~SCROLLLOCK_ON))) return p; 00129 if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY 00130 & ~SCROLLLOCK_ON))) return p; 00131 00132 // John Ioannou (roryt@hol.gr) 00133 // Athens 31/03/97 00:25am GMT+2 00134 // fix for win95 CAPSLOCK bug 00135 // first check if the user has keys with capslock and then we filter it 00136 if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY))) return p; 00137 if((p = KeyTrans.TranslateKey(keyCode, keyState & ~CAPSLOCK_ON))) return p; 00138 if((p = KeyTrans.TranslateKey(keyCode, keyState & ~ENHANCED_KEY 00139 & ~CAPSLOCK_ON))) return p; 00140 00141 return 0; // we couldn't find a suitable key translation 00142 } 00143 00144 const char *FindClosestKey(WORD keyCode, DWORD keyState, 00145 KeyTranslator &KeyTrans) { 00146 char const *p; 00147 00148 // Paul Brannan 7/20/98 00149 if(ini.get_alt_erase()) { 00150 if(keyCode == VK_BACK) { 00151 keyCode = VK_DELETE; 00152 keyState |= ENHANCED_KEY; 00153 } else if(keyCode == VK_DELETE && (keyState & ENHANCED_KEY)) { 00154 keyCode = VK_BACK; 00155 keyState &= ~ENHANCED_KEY; 00156 } 00157 } 00158 00159 DWORD ext_mode = KeyTrans.get_ext_mode(); 00160 if(ext_mode) { 00161 // Not as fast as an unrolled loop, but certainly more 00162 // compact (Paul Brannan 12/9/98) 00163 for(DWORD j = ext_mode; j >= APP_KEY; j -= APP_KEY) { 00164 if((j | ext_mode) == ext_mode) { 00165 if((p = ClosestStateKey(keyCode, keyState | j, 00166 KeyTrans))) return p; 00167 } 00168 } 00169 } 00170 return ClosestStateKey(keyCode, keyState, KeyTrans); 00171 } 00172 00173 // Paul Brannan Feb. 22, 1999 00174 int do_op(tn_ops op, TNetwork &Network, Tnclip &Clipboard) { 00175 switch(op) { 00176 case TN_ESCAPE: 00177 return TNPROMPT; 00178 case TN_SCROLLBACK: 00179 return TNSCROLLBACK; 00180 case TN_DIAL: 00181 return TNSPAWN; 00182 case TN_PASTE: 00183 if(ini.get_keyboard_paste()) Clipboard.Paste(); 00184 else return 0; 00185 break; 00186 case TN_NULL: 00187 Network.WriteString("", 1); 00188 return 0; 00189 case TN_CR: 00190 Network.WriteString("\r", 2); // CR must be followed by NUL 00191 return 0; 00192 case TN_CRLF: 00193 Network.WriteString("\r\n", 2); 00194 return 0; 00195 } 00196 return 0; 00197 } 00198 00199 int telProcessConsole(NetParams *pParams, KeyTranslator &KeyTrans, 00200 TConsole &Console, TNetwork &Network, TMouse &Mouse, 00201 Tnclip &Clipboard, HANDLE hThread) 00202 { 00203 KeyDefType_const keydef; 00204 const char *p; 00205 int p_len; 00206 unsigned int i; 00207 int opval; 00208 HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); 00209 00210 SetConsoleMode(hConsole, ini.get_enable_mouse() ? ENABLE_MOUSE_INPUT : 0); 00211 00212 const DWORD nHandle = 2; 00213 HANDLE hHandle[nHandle] = {hConsole, pParams->hExit}; 00214 00215 for (;;) { 00216 DWORD dwInput; 00217 switch (WaitForMultipleObjects(nHandle, hHandle, FALSE, INFINITE)) { 00218 case WAIT_OBJECT_0: { 00219 00220 // Paul Brannan 7/29/98 00221 if(ini.get_input_redir()) { 00222 char InputBuffer[10]; 00223 00224 // Correction from Joe Manns <joe.manns@ardenenginneers.com> 00225 // to fix race conditions (4/13/99) 00226 int bResult; 00227 bResult = ReadFile(hConsole, InputBuffer, 10, &dwInput, 0); 00228 if(bResult && dwInput == 0) return TNNOCON; 00229 00230 // no key translation for redirected input 00231 Network.WriteString(InputBuffer, dwInput); 00232 break; 00233 } 00234 00235 INPUT_RECORD InputRecord[11]; 00236 if (!ReadConsoleInput(hConsole, &InputRecord[0], 10, &dwInput)) 00237 return TNPROMPT; 00238 00239 for (i = 0; (unsigned)i < dwInput; i++){ 00240 switch (InputRecord[i].EventType) { 00241 case KEY_EVENT:{ 00242 if (KEYEVENT.bKeyDown) { 00243 00244 WORD keyCode = KEYEVENT.wVirtualKeyCode; 00245 DWORD keyState = KEYEVENT.dwControlKeyState; 00246 00247 // Paul Brannan 5/27/98 00248 // Moved the code that was here to FindClosestKey() 00249 keydef.szKeyDef = FindClosestKey(keyCode, 00250 keyState, KeyTrans); 00251 00252 if(keydef.szKeyDef) { 00253 if(!keydef.op->sendstr) 00254 if((opval = do_op(keydef.op->the_op, Network, 00255 Clipboard)) != 0) 00256 return opval; 00257 } 00258 00259 if(Network.get_line_mode()) { 00260 if(DoLineModeSpecial(KEYEVENT_CHAR, Console, Network, pParams)) 00261 continue; 00262 } 00263 00264 p = keydef.szKeyDef; 00265 if (p == NULL) { // if we don't have a translator 00266 if(!KEYEVENT_CHAR) continue; 00267 p_len = 1; 00268 p = KEYEVENT_PCHAR; 00269 } else { 00270 p_len = strlen(p); 00271 } 00272 00273 // Local echo (Paul Brannan 5/16/98) 00274 DoEcho(p, p_len, Console, Network, pParams); 00275 // Line mode (Paul Brannan 12/31/98) 00276 DoLineMode(p, p_len, Console, Network); 00277 } 00278 } 00279 break; 00280 00281 case MOUSE_EVENT: 00282 if(!InputRecord[i].Event.MouseEvent.dwEventFlags) { 00283 ResetEvent(pParams->hUnPause); 00284 SetEvent(pParams->hPause); 00285 while (!*pParams->bNetPaused); // thread paused 00286 // SuspendThread(hThread); 00287 00288 // Put the mouse's X and Y coords back into the 00289 // input buffer 00290 DWORD Result; 00291 WriteConsoleInput(hConsole, &InputRecord[i], 1, 00292 &Result); 00293 00294 Mouse.doMouse(); 00295 00296 SetEvent(pParams->hUnPause); 00297 // ResumeThread(hThread); 00298 } 00299 break; 00300 00301 case FOCUS_EVENT: 00302 break; 00303 case WINDOW_BUFFER_SIZE_EVENT: 00304 // FIX ME!! This should take care of the window re-sizing bug 00305 // Unfortunately, it doesn't. 00306 Console.sync(); 00307 Network.do_naws(Console.GetWidth(), Console.GetHeight()); 00308 break; 00309 } 00310 00311 } // keep going until no more input 00312 break; 00313 } 00314 default: 00315 return TNNOCON; 00316 } 00317 } 00318 } 00319 00320 WORD scrollkeys() { 00321 HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); 00322 INPUT_RECORD InputRecord; 00323 BOOL done = FALSE; 00324 00325 while (!done) { 00326 DWORD dwInput; 00327 WaitForSingleObject( hConsole, INFINITE ); 00328 if (!ReadConsoleInput(hConsole, &InputRecord, 1, &dwInput)){ 00329 done = TRUE; 00330 continue; 00331 } 00332 if (InputRecord.EventType == KEY_EVENT && 00333 InputRecord.Event.KeyEvent.bKeyDown ) { 00334 // Why not just return the key code? (Paul Brannan 12/5/98) 00335 return InputRecord.Event.KeyEvent.wVirtualKeyCode; 00336 } else if(InputRecord.EventType == MOUSE_EVENT) { 00337 if(!InputRecord.Event.MouseEvent.dwEventFlags) { 00338 // Put the mouse's X and Y coords back into the input buffer 00339 WriteConsoleInput(hConsole, &InputRecord, 1, &dwInput); 00340 return SC_MOUSE; 00341 } 00342 } 00343 } 00344 return SC_ESC; 00345 } 00346 00347 // FIX ME!! This is more evidence that tncon.cpp ought to have class structure 00348 // (Paul Brannan 12/10/98) 00349 00350 // Bryan Montgomery 10/14/98 00351 static TNetwork net; 00352 void setTNetwork(TNetwork tnet) { 00353 net = tnet; 00354 } 00355 00356 // Thomas Briggs 8/17/98 00357 BOOL WINAPI ControlEventHandler(DWORD event) { 00358 switch(event) { 00359 case CTRL_BREAK_EVENT: 00360 // Bryan Montgomery 10/14/98 00361 if(ini.get_control_break_as_c()) net.WriteString("\x3",1); 00362 return TRUE; 00363 default: 00364 return FALSE; 00365 } 00366 } Generated on Fri May 25 2012 04:15:34 for ReactOS by
1.7.6.1
|