+/*
+ * window.c - the PuTTY(tel) main program, which runs a PuTTY terminal
+ * emulator and backend in a window.
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
+#include <limits.h>
#include <assert.h>
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
static void *backhandle;
static struct unicode_data ucsdata;
-static int session_closed;
+static int must_close_session, session_closed;
static int reconfiguring = FALSE;
static const struct telnet_special *specials = NULL;
if (error) {
char *str = dupprintf("%s Error", appname);
sprintf(msg, "Unable to open connection to\n"
- "%.800s\n" "%s", cfg.host, error);
+ "%.800s\n" "%s", cfg_dest(&cfg), error);
MessageBox(NULL, msg, str, MB_ICONERROR | MB_OK);
sfree(str);
exit(0);
term_set_focus(term, GetForegroundWindow() == hwnd);
UpdateWindow(hwnd);
- if (GetMessage(&msg, NULL, 0, 0) == 1) {
- while (msg.message != WM_QUIT) {
+ while (1) {
+ HANDLE *handles;
+ int nhandles, n;
+
+ handles = handle_get_events(&nhandles);
+
+ n = MsgWaitForMultipleObjects(nhandles, handles, FALSE, INFINITE,
+ QS_ALLINPUT);
+
+ if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
+ handle_got_event(handles[n - WAIT_OBJECT_0]);
+ sfree(handles);
+ if (must_close_session)
+ close_session();
+ continue;
+ }
+
+ sfree(handles);
+
+ if (GetMessage(&msg, NULL, 0, 0) != 1)
+ break;
+ do {
+ if (msg.message == WM_QUIT)
+ goto finished; /* two-level break */
+
if (!(IsWindow(logbox) && IsDialogMessage(logbox, &msg)))
DispatchMessage(&msg);
/* Send the paste buffer if there's anything to send */
* we've delayed, reading the socket, writing, and repainting
* the window.
*/
- if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
- continue;
-
- /* The messages seem unreliable; especially if we're being tricky */
- term_set_focus(term, GetForegroundWindow() == hwnd);
+ if (must_close_session)
+ close_session();
+ } while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE));
- net_pending_errors();
+ /* The messages seem unreliable; especially if we're being tricky */
+ term_set_focus(term, GetForegroundWindow() == hwnd);
- /* There's no point rescanning everything in the message queue
- * so we do an apparently unnecessary wait here
- */
- WaitMessage();
- if (GetMessage(&msg, NULL, 0, 0) != 1)
- break;
- }
+ net_pending_errors();
}
+ finished:
cleanup_exit(msg.wParam); /* this doesn't return... */
return msg.wParam; /* ... but optimiser doesn't know */
}
if (cfg.close_on_exit == FORCE_ON)
PostQuitMessage(1);
else {
- close_session();
+ must_close_session = TRUE;
}
}
{
static int reentering = 0;
extern int select_result(WPARAM, LPARAM);
- int ret;
if (reentering)
return; /* don't unpend the pending */
reentering = 1;
- ret = select_result(wParam, lParam);
+ select_result(wParam, lParam);
reentering = 0;
-
- if (ret == 0 && !session_closed) {
- /* Abnormal exits will already have set session_closed and taken
- * appropriate action. */
- if (cfg.close_on_exit == FORCE_ON ||
- cfg.close_on_exit == AUTO) PostQuitMessage(0);
- else {
- close_session();
- session_closed = TRUE;
- MessageBox(hwnd, "Connection closed by remote host",
- appname, MB_OK | MB_ICONINFORMATION);
- }
- }
}
/*
static int resizing;
-void notify_remote_exit(void *fe) { /* stub not needed in this frontend */ }
+void notify_remote_exit(void *fe)
+{
+ int exitcode;
+
+ if (!session_closed &&
+ (exitcode = back->exitcode(backhandle)) >= 0) {
+ /* Abnormal exits will already have set session_closed and taken
+ * appropriate action. */
+ if (cfg.close_on_exit == FORCE_ON ||
+ (cfg.close_on_exit == AUTO && exitcode != INT_MAX)) {
+ PostQuitMessage(0);
+ } else {
+ must_close_session = TRUE;
+ session_closed = TRUE;
+ /* exitcode == INT_MAX indicates that the connection was closed
+ * by a fatal error, so an error box will be coming our way and
+ * we should not generate this informational one. */
+ if (exitcode != INT_MAX)
+ MessageBox(hwnd, "Connection closed by remote host",
+ appname, MB_OK | MB_ICONINFORMATION);
+ }
+ }
+}
void timer_change_notify(long next)
{