timer_id = SetTimer(hwnd, 1, 500, NULL);
if (!has_focus) timer_id = SetTimer(hwnd, 1, 2000, NULL); else if (cfg.blinktext) timer_id = SetTimer(hwnd, 1, 250, NULL); else timer_id = SetTimer(hwnd, 1, 500, NULL);
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {    static char appname[] = "PuTTY";    WORD winsock_ver;    WSADATA wsadata;    WNDCLASS wndclass;    MSG msg;    int guess_width, guess_height;    putty_inst = inst;    winsock_ver = MAKEWORD(1, 1);    if (WSAStartup(winsock_ver, &wsadata)) {	MessageBox(NULL, "Unable to initialise WinSock", "WinSock Error",		   MB_OK | MB_ICONEXCLAMATION);	return 1;    }    if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {	MessageBox(NULL, "WinSock version is incompatible with 1.1",		   "WinSock Error", MB_OK | MB_ICONEXCLAMATION);	WSACleanup();	return 1;    }    /* WISHLIST: maybe allow config tweaking even if winsock not present? */    InitCommonControls();    /*     * Process the command line.     */    {	char *p;	default_protocol = DEFAULT_PROTOCOL;	default_port = DEFAULT_PORT;	do_defaults(NULL);	p = cmdline;	while (*p && isspace(*p)) p++;	/*	 * Process command line options first. Yes, this can be	 * done better, and it will be as soon as I have the	 * energy...	 */	while (*p == '-') {	    char *q = p + strcspn(p, " \t");	    p++;	    if (q == p + 3 &&		tolower(p[0]) == 's' &&		tolower(p[1]) == 's' &&		tolower(p[2]) == 'h') {		default_protocol = cfg.protocol = PROT_SSH;		default_port = cfg.port = 22;	    } else if (q == p + 3 &&		tolower(p[0]) == 'l' &&		tolower(p[1]) == 'o' &&		tolower(p[2]) == 'g') {                logfile = "putty.log";	    }	    p = q + strspn(q, " \t");	}	/*	 * An initial @ means to activate a saved session.	 */	if (*p == '@') {	    do_defaults (p+1);	    if (!*cfg.host && !do_config()) {		WSACleanup();		return 0;	    }	} else if (*p == '&') {	    /*	     * An initial & means we've been given a command line	     * containing the hex value of a HANDLE for a file	     * mapping object, which we must then extract as a	     * config.	     */	    HANDLE filemap;	    Config *cp;	    if (sscanf(p+1, "%p", &filemap) == 1 &&		(cp = MapViewOfFile(filemap, FILE_MAP_READ,				    0, 0, sizeof(Config))) != NULL) {		cfg = *cp;		UnmapViewOfFile(cp);		CloseHandle(filemap);	    } else if (!do_config()) {		WSACleanup();		return 0;	    }	} else if (*p) {	    char *q = p;            /*             * If the hostname starts with "telnet://", set the             * protocol to Telnet and process the string as a             * Telnet URL.             */            if (!strncmp(q, "telnet://", 9)) {                char c;                q += 9;                cfg.protocol = PROT_TELNET;                p = q;                while (*p && *p != ':' && *p != '/') p++;                c = *p;                if (*p)                    *p++ = '\0';                if (c == ':')                    cfg.port = atoi(p);                else                    cfg.port = -1;                strncpy (cfg.host, q, sizeof(cfg.host)-1);                cfg.host[sizeof(cfg.host)-1] = '\0';            } else {                while (*p && !isspace(*p)) p++;                if (*p)                    *p++ = '\0';                strncpy (cfg.host, q, sizeof(cfg.host)-1);                cfg.host[sizeof(cfg.host)-1] = '\0';                while (*p && isspace(*p)) p++;                if (*p)                    cfg.port = atoi(p);                else                    cfg.port = -1;            }	} else {	    if (!do_config()) {		WSACleanup();		return 0;	    }	}    }    /*     * Select protocol. This is farmed out into a table in a     * separate file to enable an ssh-free variant.     */    {        int i;        back = NULL;        for (i = 0; backends[i].backend != NULL; i++)            if (backends[i].protocol == cfg.protocol) {                back = backends[i].backend;                break;            }        if (back == NULL) {            MessageBox(NULL, "Unsupported protocol number found",                       "PuTTY Internal Error", MB_OK | MB_ICONEXCLAMATION);            WSACleanup();            return 1;        }    }    ldisc = (cfg.ldisc_term ? &ldisc_term : &ldisc_simple);    if (!prev) {	wndclass.style         = 0;	wndclass.lpfnWndProc   = WndProc;	wndclass.cbClsExtra    = 0;	wndclass.cbWndExtra    = 0;	wndclass.hInstance     = inst;	wndclass.hIcon         = LoadIcon (inst,					   MAKEINTRESOURCE(IDI_MAINICON));	wndclass.hCursor       = LoadCursor (NULL, IDC_IBEAM);	wndclass.hbrBackground = GetStockObject (BLACK_BRUSH);	wndclass.lpszMenuName  = NULL;	wndclass.lpszClassName = appname;	RegisterClass (&wndclass);    }    hwnd = NULL;    savelines = cfg.savelines;    term_init();    cfgtopalette();    /*     * Guess some defaults for the window size. This all gets     * updated later, so we don't really care too much. However, we     * do want the font width/height guesses to correspond to a     * large font rather than a small one...     */        font_width = 10;    font_height = 20;    extra_width = 25;    extra_height = 28;    term_size (cfg.height, cfg.width, cfg.savelines);    guess_width = extra_width + font_width * cols;    guess_height = extra_height + font_height * rows;    {	RECT r;	HWND w = GetDesktopWindow();	GetWindowRect (w, &r);	if (guess_width > r.right - r.left)	    guess_width = r.right - r.left;	if (guess_height > r.bottom - r.top)	    guess_height = r.bottom - r.top;    }    hwnd = CreateWindow (appname, appname,			 WS_OVERLAPPEDWINDOW | WS_VSCROLL,			 CW_USEDEFAULT, CW_USEDEFAULT,			 guess_width, guess_height,			 NULL, NULL, inst, NULL);    /*     * Initialise the fonts, simultaneously correcting the guesses     * for font_{width,height}.     */    bold_mode = cfg.bold_colour ? BOLD_COLOURS : BOLD_FONT;    und_mode = UND_FONT;    init_fonts(0);    /*     * Correct the guesses for extra_{width,height}.     */    {	RECT cr, wr;	GetWindowRect (hwnd, &wr);	GetClientRect (hwnd, &cr);	extra_width = wr.right - wr.left - cr.right + cr.left;	extra_height = wr.bottom - wr.top - cr.bottom + cr.top;    }    /*     * Resize the window, now we know what size we _really_ want it     * to be.     */    guess_width = extra_width + font_width * cols;    guess_height = extra_height + font_height * rows;    SendMessage (hwnd, WM_IGNORE_SIZE, 0, 0);    SetWindowPos (hwnd, NULL, 0, 0, guess_width, guess_height,		  SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);    /*     * Initialise the scroll bar.     */    {	SCROLLINFO si;	si.cbSize = sizeof(si);	si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_DISABLENOSCROLL;	si.nMin = 0;	si.nMax = rows-1;	si.nPage = rows;	si.nPos = 0;	SetScrollInfo (hwnd, SB_VERT, &si, FALSE);    }    /*     * Start up the telnet connection.     */    {	char *error;	char msg[1024];	char *realhost;	error = back->init (hwnd, cfg.host, cfg.port, &realhost);	if (error) {	    sprintf(msg, "Unable to open connection:\n%s", error);	    MessageBox(NULL, msg, "PuTTY Error", MB_ICONERROR | MB_OK);	    return 0;	}	window_name = icon_name = NULL;	sprintf(msg, "%s - PuTTY", realhost);	set_title (msg);	set_icon (msg);    }    session_closed = FALSE;    /*     * Set up the input and output buffers.     */    inbuf_reap = inbuf_head = 0;    outbuf_reap = outbuf_head = 0;    /*      * Choose unscroll method     */    unscroll_event = US_DISP;    /*     * Prepare the mouse handler.     */    lastact = MA_NOTHING;    lastbtn = MB_NOTHING;    dbltime = GetDoubleClickTime();    /*     * Set up the session-control options on the system menu.     */    {	HMENU m = GetSystemMenu (hwnd, FALSE);	HMENU p,s;	int i;	AppendMenu (m, MF_SEPARATOR, 0, 0);	if (cfg.protocol == PROT_TELNET) {	    p = CreateMenu();	    AppendMenu (p, MF_ENABLED, IDM_TEL_AYT, "Are You There");	    AppendMenu (p, MF_ENABLED, IDM_TEL_BRK, "Break");	    AppendMenu (p, MF_ENABLED, IDM_TEL_SYNCH, "Synch");	    AppendMenu (p, MF_SEPARATOR, 0, 0);	    AppendMenu (p, MF_ENABLED, IDM_TEL_EC, "Erase Character");	    AppendMenu (p, MF_ENABLED, IDM_TEL_EL, "Erase Line");	    AppendMenu (p, MF_ENABLED, IDM_TEL_GA, "Go Ahead");	    AppendMenu (p, MF_ENABLED, IDM_TEL_NOP, "No Operation");	    AppendMenu (p, MF_SEPARATOR, 0, 0);	    AppendMenu (p, MF_ENABLED, IDM_TEL_ABORT, "Abort Process");	    AppendMenu (p, MF_ENABLED, IDM_TEL_AO, "Abort Output");	    AppendMenu (p, MF_ENABLED, IDM_TEL_IP, "Interrupt Process");	    AppendMenu (p, MF_ENABLED, IDM_TEL_SUSP, "Suspend Process");	    AppendMenu (p, MF_SEPARATOR, 0, 0);	    AppendMenu (p, MF_ENABLED, IDM_TEL_EOR, "End Of Record");	    AppendMenu (p, MF_ENABLED, IDM_TEL_EOF, "End Of File");	    AppendMenu (m, MF_POPUP | MF_ENABLED, (UINT) p, "Telnet Command");	    AppendMenu (m, MF_SEPARATOR, 0, 0);	}	AppendMenu (m, MF_ENABLED, IDM_SHOWLOG, "&Event Log");	AppendMenu (m, MF_SEPARATOR, 0, 0);	AppendMenu (m, MF_ENABLED, IDM_NEWSESS, "Ne&w Session");	AppendMenu (m, MF_ENABLED, IDM_DUPSESS, "&Duplicate Session");	s = CreateMenu();	get_sesslist(TRUE);	for (i = 1 ; i < ((nsessions < 256) ? nsessions : 256) ; i++)	  AppendMenu (s, MF_ENABLED, IDM_SAVED_MIN + (16 * i) , sessions[i]);	AppendMenu (m, MF_POPUP | MF_ENABLED, (UINT) s, "Sa&ved Sessions");	AppendMenu (m, MF_ENABLED, IDM_RECONF, "Chan&ge Settings");	AppendMenu (m, MF_SEPARATOR, 0, 0);	AppendMenu (m, MF_ENABLED, IDM_CLRSB, "C&lear Scrollback");	AppendMenu (m, MF_ENABLED, IDM_RESET, "Rese&t Terminal");	AppendMenu (m, MF_SEPARATOR, 0, 0);	AppendMenu (m, MF_ENABLED, IDM_ABOUT, "&About PuTTY");    }    /*     * Finally show the window!     */    ShowWindow (hwnd, show);    /*     * Set the palette up.     */    pal = NULL;    logpal = NULL;    init_palette();    has_focus = (GetForegroundWindow() == hwnd);    UpdateWindow (hwnd);    {	int timer_id = 0, long_timer = 0;	while (GetMessage (&msg, NULL, 0, 0) == 1) {	    /* Sometimes DispatchMessage calls routines that use their own	     * GetMessage loop, setup this timer so we get some control back.	     *	     * Also call term_update() from the timer so that if the host	     * is sending data flat out we still do redraws.	     */	    if(timer_id && long_timer) {		KillTimer(hwnd, timer_id);		long_timer = timer_id = 0;	    }	    if(!timer_id)		timer_id = SetTimer(hwnd, 1, 20, NULL);	    DispatchMessage (&msg);	    /* This is too fast, but I'll leave it for now 'cause it shows	     * how often term_update is called (far too often at times!)	     */	    term_blink(0);	    /* If there's nothing new in the queue then we can do everything	     * we've delayed, reading the socket, writing, and repainting	     * the window.	     */	    if (!PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) {		if (pending_netevent) {		    enact_pending_netevent();		    term_blink(1);		}	    } else continue;	    if (!PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) {		if (timer_id) {		    KillTimer(hwnd, timer_id);		    timer_id = 0;		}		if (inbuf_reap != inbuf_head)		    term_out();		term_update();		timer_id = SetTimer(hwnd, 1, 500, NULL);		long_timer = 1;	    }	}    }    /*     * Clean up.     */    {	int i;	for (i=0; i<8; i++)	    if (fonts[i])		DeleteObject(fonts[i]);    }    sfree(logpal);    if (pal)	DeleteObject(pal);    WSACleanup();    if (cfg.protocol == PROT_SSH) {	random_save_seed();#ifdef MSCRYPTOAPI	crypto_wrapup();#endif    }    return msg.wParam;}