Add asynchronous callback capability to the askappend() alert box.
[u/mdw/putty] / macosx / osxwin.m
index a54f771..0b0c3ff 100644 (file)
 {
     NSRect rect = { {0,0}, {0,0} };
 
+    alert_ctx = NULL;
+
     cfg = aCfg;                               /* structure copy */
 
     init_ucs(&ucsdata, cfg.line_codepage, cfg.utf8_override,
        if (realhost)
            sfree(realhost);           /* FIXME: do something with this */
     }
+    back->provide_logctx(backhandle, logctx);
 
     /*
      * Create a line discipline. (This must be done after creating
      * terminal, the backend, the ldisc, the logctx, you name it.
      * Do so.
      */
+    sfree(alert_ctx);
     [super dealloc];
 }
 
@@ -778,6 +782,70 @@ printf("n=%d c=U+%04x cm=U+%04x m=%08x\n", n, c, cm, m);
     return term_data(term, is_stderr, data, len);
 }
 
+- (void)startAlert:(NSAlert *)alert
+    withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx
+{
+    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
+    contextInfo:(void *)contextInfo
+{
+    [self performSelectorOnMainThread:
+     @selector(alertSheetDidFinishEnding:)
+     withObject:[NSNumber numberWithInt:returnCode]
+     waitUntilDone:NO];
+}
+
+- (void)alertSheetDidFinishEnding:(id)object
+{
+    int returnCode = [object intValue];
+
+    alert_callback(alert_ctx, returnCode);   /* transfers ownership of ctx */
+
+    /*
+     * If there's an alert in our queue (either already or because
+     * the callback just queued it), start it.
+     */
+    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;
+    }
+}
+
 @end
 
 int from_backend(void *frontend, int is_stderr, const char *data, int len)