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