Fix segfault on forcible window closure.
[u/mdw/putty] / macosx / osxwin.m
index 0424b0b..59cc4bf 100644 (file)
        if (realhost)
            sfree(realhost);           /* FIXME: do something with this */
     }
+    back->provide_logctx(backhandle, logctx);
 
     /*
      * Create a line discipline. (This must be done after creating
      */
     [self center];                    /* :-) */
 
+    exited = FALSE;
+
     return self;
 }
 
      * Do so.
      */
     sfree(alert_ctx);
+    if (back)
+       back->free(backhandle);
+    if (ldisc)
+       ldisc_free(ldisc);
+    /* ldisc must be freed before term, since ldisc_free expects term
+     * still to be around. */
+    if (logctx)
+       log_free(logctx);
+    if (term)
+       term_free(term);
     [super dealloc];
 }
 
     char coutput[32];
     int use_coutput = FALSE, special = FALSE, start, end;
 
-printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
+//printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
 
     /*
      * FIXME: Alt+numberpad codes.
@@ -784,11 +797,27 @@ printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
 - (void)startAlert:(NSAlert *)alert
     withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx
 {
-    alert_callback = callback;
-    alert_ctx = ctx;                /* NB this is assumed to need freeing! */
-    [alert beginSheetModalForWindow:self modalDelegate:self
-     didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)
-     contextInfo:NULL];
+    if (alert_ctx || alert_qhead) {
+       /*
+        * Queue this alert to be shown later.
+        */
+       struct alert_queue *qitem = snew(struct alert_queue);
+       qitem->next = NULL;
+       qitem->alert = alert;
+       qitem->callback = callback;
+       qitem->ctx = ctx;
+       if (alert_qtail)
+           alert_qtail->next = qitem;
+       else
+           alert_qhead = qitem;
+       alert_qtail = qitem;
+    } else {
+       alert_callback = callback;
+       alert_ctx = ctx;               /* NB this is assumed to need freeing! */
+       [alert beginSheetModalForWindow:self modalDelegate:self
+        didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)
+        contextInfo:NULL];
+    }
 }
 
 - (void)alertSheetDidEnd:(NSAlert *)alert returnCode:(int)returnCode
@@ -803,19 +832,57 @@ printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
 - (void)alertSheetDidFinishEnding:(id)object
 {
     int returnCode = [object intValue];
-    void (*this_callback)(void *, int);
-    void *this_ctx;
+
+    alert_callback(alert_ctx, returnCode);   /* transfers ownership of ctx */
 
     /*
-     * We must save the values of our alert_callback and alert_ctx
-     * fields, in case they are set up again by the callback
-     * function!
+     * If there's an alert in our queue (either already or because
+     * the callback just queued it), start it.
      */
-    this_callback = alert_callback;
-    this_ctx = alert_ctx;
-    alert_ctx = NULL;
+    if (alert_qhead) {
+       struct alert_queue *qnext;
+
+       alert_callback = alert_qhead->callback;
+       alert_ctx = alert_qhead->ctx;
+       [alert_qhead->alert beginSheetModalForWindow:self modalDelegate:self
+        didEndSelector:@selector(alertSheetDidEnd:returnCode:contextInfo:)
+        contextInfo:NULL];
+
+       qnext = alert_qhead->next;
+       sfree(alert_qhead);
+       alert_qhead = qnext;
+       if (!qnext)
+           alert_qtail = NULL;
+    } else {
+       alert_ctx = NULL;
+    }
+}
+
+- (void)notifyRemoteExit
+{
+    int exitcode;
 
-    this_callback(this_ctx, returnCode);   /* transfers ownership of ctx */
+    if (!exited && (exitcode = back->exitcode(backhandle)) >= 0)
+       [self endSession:(exitcode == 0)];
+}
+
+- (void)endSession:(int)clean
+{
+    exited = TRUE;
+    if (ldisc) {
+       ldisc_free(ldisc);
+       ldisc = NULL;
+    }
+    if (back) {
+       back->free(backhandle);
+       backhandle = NULL;
+       back = NULL;
+       //FIXME: update specials menu;
+    }
+    if (cfg.close_on_exit == FORCE_ON ||
+       (cfg.close_on_exit == AUTO && clean))
+       [self close];
+    // FIXME: else show restart menu item
 }
 
 @end
@@ -831,23 +898,11 @@ void frontend_keypress(void *handle)
     /* FIXME */
 }
 
-void connection_fatal(void *frontend, char *p, ...)
-{
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME: proper OS X GUI stuff */
-    va_list ap;
-    fprintf(stderr, "FATAL ERROR: ");
-    va_start(ap, p);
-    vfprintf(stderr, p, ap);
-    va_end(ap);
-    fputc('\n', stderr);
-    exit(1);
-}
-
 void notify_remote_exit(void *frontend)
 {
-    //SessionWindow *win = (SessionWindow *)frontend;
-    /* FIXME */
+    SessionWindow *win = (SessionWindow *)frontend;
+
+    [win notifyRemoteExit];
 }
 
 void ldisc_update(void *frontend, int echo, int edit)