Add a preference list for SSH-2 key exchange algorithms, on a new "Kex" panel
[u/mdw/putty] / mac / mac.c
index a0bc998..8dde3e1 100644 (file)
--- a/mac/mac.c
+++ b/mac/mac.c
@@ -1,4 +1,4 @@
-/* $Id: mac.c,v 1.49 2003/02/15 16:22:15 ben Exp $ */
+/* $Id$ */
 /*
  * Copyright (c) 1999, 2003 Ben Harris
  * All rights reserved.
@@ -31,6 +31,7 @@
 #include <MacTypes.h>
 #include <AEDataModel.h>
 #include <AppleEvents.h>
+#include <Controls.h>
 #include <Quickdraw.h>
 #include <Fonts.h>
 #include <MacWindows.h>
@@ -61,6 +62,7 @@
 #include "macresid.h"
 #include "putty.h"
 #include "ssh.h"
+#include "terminal.h"
 #include "mac.h"
 
 Session *sesslist;
@@ -68,6 +70,7 @@ Session *sesslist;
 static int cold = 1;
 static int borednow = FALSE;
 struct mac_gestalts mac_gestalts;
+UInt32 sleeptime;
 
 static void mac_startup(void);
 static void mac_eventloop(void);
@@ -76,6 +79,7 @@ static void mac_event(EventRecord *);
 static void mac_contentclick(WindowPtr, EventRecord *);
 static void mac_growwindow(WindowPtr, EventRecord *);
 static void mac_activatewindow(WindowPtr, EventRecord *);
+static void mac_suspendresume(EventRecord *);
 static void mac_activateabout(WindowPtr, EventRecord *);
 static void mac_updatewindow(WindowPtr);
 static void mac_updatelicence(WindowPtr);
@@ -156,6 +160,9 @@ static void mac_startup(void) {
     if (Gestalt(gestaltWindowMgrAttr, &mac_gestalts.windattr) != noErr ||
        &SetWindowContentColor == kUnresolvedCFragSymbolAddress)
        mac_gestalts.windattr = 0;
+    /* Mac OS 8.5 Menu Manager? */
+    if (Gestalt(gestaltMenuMgrAttr, &mac_gestalts.menuattr) != noErr)
+       mac_gestalts.menuattr = 0;
 #endif
     /* Text Encoding Conversion Manager? */
     if (
@@ -188,6 +195,11 @@ static void mac_startup(void) {
        fatalbox("Unable to create menu bar.");
     SetMenuBar(menuBar);
     AppendResMenu(GetMenuHandle(mApple), 'DRVR');
+    if (mac_gestalts.menuattr & gestaltMenuMgrAquaLayoutMask) {
+       DeleteMenuItem(GetMenuHandle(mFile), iQuit);
+       /* Also delete the separator above the Quit item. */
+       DeleteMenuItem(GetMenuHandle(mFile), iQuit - 1);
+    }
     mac_adjustmenus();
     DrawMenuBar();
     InitCursor();
@@ -238,16 +250,28 @@ static void mac_eventloop(void) {
     RgnHandle cursrgn;
 
     cursrgn = NewRgn();
+    sleeptime = 0;
     for (;;) {
        mac_adjustcursor(cursrgn);
-       gotevent = WaitNextEvent(everyEvent, &event, LONG_MAX, cursrgn);
+       gotevent = WaitNextEvent(everyEvent, &event, sleeptime, cursrgn);
+       /*
+        * XXX For now, limit sleep time to 1/10 s to work around
+        * wake-before-sleep race in MacTCP code.
+        */
+       sleeptime = 6;
        mac_adjustcursor(cursrgn);
-       if (gotevent)
+       if (gotevent) {
+           /* Ensure we get a null event when the real ones run out. */
+           sleeptime = 0;
            mac_event(&event);
-       if (borednow)
-           cleanup_exit(0);
+           if (borednow)
+               cleanup_exit(0);
+       }
        sk_poll();
-       mac_pollterm();
+       if (!gotevent)
+           mac_pollterm();
+       if (mac_gestalts.apprvers >= 0x100 && mac_frontwindow() != NULL)
+           IdleControls(mac_frontwindow());
     }
     DisposeRgn(cursrgn);
 }
@@ -323,6 +347,13 @@ static void mac_event(EventRecord *event) {
         }
         break;
 #endif
+      case osEvt:
+       switch ((event->message & osEvtMessageMask) >> 24) {
+         case suspendResumeMessage:
+           mac_suspendresume(event);
+           break;
+       }
+       break;
       case kHighLevelEvent:
        AEProcessAppleEvent(event); /* errors? */
        break;
@@ -377,7 +408,7 @@ static int mac_windowtype(WindowPtr window)
 static void mac_keypress(EventRecord *event) {
     WindowPtr window;
 
-    window = FrontWindow();
+    window = mac_frontwindow();
     /*
      * Check for a command-key combination, but ignore it if it counts
      * as a meta-key combination and we're in a terminal window.
@@ -388,7 +419,7 @@ static void mac_keypress(EventRecord *event) {
        mac_adjustmenus();
        mac_menucommand(MenuKey(event->message & charCodeMask));
     } else {
-       if (mac_wininfo(window)->key != NULL)
+       if (window != NULL && mac_wininfo(window)->key != NULL)
            (*mac_wininfo(window)->key)(window, event);
     }       
 }
@@ -402,7 +433,7 @@ static void mac_menucommand(long result) {
 
     menu = HiWord(result);
     item = LoWord(result);
-    window = FrontWindow();
+    window = mac_frontwindow();
     /* Things which do the same whatever window we're in. */
     switch (menu) {
       case mApple:
@@ -445,7 +476,7 @@ static void mac_menucommand(long result) {
         break;
     }
     /* If we get here, handling is up to window-specific code. */
-    if (mac_wininfo(window)->menu != NULL)
+    if (window != NULL && mac_wininfo(window)->menu != NULL)
        (*mac_wininfo(window)->menu)(window, menu, item);
 
   done:
@@ -467,6 +498,27 @@ static void mac_closewindow(WindowPtr window) {
     }
 }
 
+static void mac_suspendresume(EventRecord *event)
+{
+    WindowPtr front;
+    EventRecord fakeevent;
+
+    /*
+     * We're called either before we're suspended or after we're
+     * resumed, so we're the front application at this point.
+     */
+    front = FrontWindow();
+    if (front != NULL) {
+       fakeevent.what = activateEvt;
+       fakeevent.message = (UInt32)front;
+       fakeevent.when = event->when;
+       fakeevent.where = event->where;
+       fakeevent.modifiers =
+           (event->message & resumeFlag) ? activeFlag : 0;
+       mac_activatewindow(front, &fakeevent);
+    }
+}
+
 static void mac_zoomwindow(WindowPtr window, short part) {
 
     /* FIXME: do something */
@@ -483,7 +535,7 @@ static void mac_adjustmenus(void) {
     WindowPtr window;
     MenuHandle menu;
 
-    window = FrontWindow();
+    window = mac_frontwindow();
     menu = GetMenuHandle(mApple);
     EnableItem(menu, 0);
     EnableItem(menu, iAbout);
@@ -497,7 +549,7 @@ static void mac_adjustmenus(void) {
        DisableItem(menu, iClose);
     EnableItem(menu, iQuit);
 
-    if (mac_wininfo(window)->adjustmenus != NULL)
+    if (window != NULL && mac_wininfo(window)->adjustmenus != NULL)
        (*mac_wininfo(window)->adjustmenus)(window);
     else {
        DisableItem(menu, iSave);
@@ -609,11 +661,13 @@ int agent_exists(void)
     return FALSE;
 }
 
-void agent_query(void *in, int inlen, void **out, int *outlen)
+int agent_query(void *in, int inlen, void **out, int *outlen,
+               void (*callback)(void *, void *, int), void *callback_ctx)
 {
 
     *out = NULL;
     *outlen = 0;
+    return 1;
 }
 
 /* Temporary null routines for testing. */
@@ -621,10 +675,36 @@ void agent_query(void *in, int inlen, void **out, int *outlen)
 void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
                         char *keystr, char *fingerprint)
 {
+    Str255 stuff;
+    Session *s = frontend;
+
+    /*
+     * This function is horribly wrong.  For one thing, the alert
+     * shouldn't be modal, it should be movable modal, or a sheet in
+     * Aqua.  Also, PuTTY might be in the background, in which case we
+     * should use the Notification Manager to wake up the user.  In
+     * any case, we shouldn't hold up processing of other connections'
+     * data just because this one's waiting for the user.  It should
+     * also handle a host key cache, of course, and see the note below
+     * about closing the connection.  All in all, a bit of a mess
+     * really.
+     */
 
+    stuff[0] = sprintf((char *)(&stuff[1]),
+                      "The server's key fingerprint is: %s\n"
+                      "Continue connecting?", fingerprint);
+    ParamText(stuff, NULL, NULL, NULL);
+    if (CautionAlert(wQuestion, NULL) == 2) {
+       /*
+        * User chose "Cancel".  Unfortunately, if I tear the
+        * connection down here, Bad Things happen when I return.  I
+        * think this function should actually return something
+        * telling the SSH code to abandon the connection.
+        */
+    }
 }
 
-void askcipher(void *frontend, char *ciphername, int cs)
+void askalg(void *frontend, const char *algtype, const char *algname)
 {
 
 }
@@ -694,6 +774,16 @@ void platform_get_x11_auth(char *display, int *proto,
     /* SGT: I have no idea whether Mac X servers need anything here. */
 }
 
+void update_specials_menu(void *frontend)
+{
+    Session *s = frontend;
+    WindowPtr front;
+
+    front = mac_frontwindow();
+    if (front != NULL && mac_windowsession(front) == s)
+       mac_adjustmenus();
+}
+
 /*
  * Local Variables:
  * c-file-style: "simon"