]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - mac/macpgen.c
Cleanups of the GSSAPI support. On Windows, standard GSS libraries
[PuTTY.git] / mac / macpgen.c
1 /* $Id$ */
2 /*
3  * Copyright (c) 1999, 2003 Ben Harris
4  * All rights reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use,
10  * copy, modify, merge, publish, distribute, sublicense, and/or
11  * sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following
13  * conditions:
14  * 
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27
28 /*
29  * macpgen.c - PuTTYgen for Mac OS
30  */
31
32 #include <MacTypes.h>
33 #include <AEDataModel.h>
34 #include <AppleEvents.h>
35 #include <Quickdraw.h>
36 #include <Fonts.h>
37 #include <MacWindows.h>
38 #include <Menus.h>
39 #include <TextEdit.h>
40 #include <Appearance.h>
41 #include <CodeFragments.h>
42 #include <Dialogs.h>
43 #include <Devices.h>
44 #include <DiskInit.h>
45 #include <Gestalt.h>
46 #include <LowMem.h>
47 #include <Navigation.h>
48 #include <Resources.h>
49 #include <Script.h>
50 #include <TextCommon.h>
51 #include <ToolUtils.h>
52 #include <UnicodeConverter.h>
53
54 #include <assert.h>
55 #include <limits.h>
56 #include <stdarg.h>
57 #include <stdlib.h>             /* putty.h needs size_t */
58 #include <stdio.h>              /* for vsprintf */
59
60 #define PUTTY_DO_GLOBALS
61
62 #include "macpgrid.h"
63 #include "putty.h"
64 #include "ssh.h"
65 #include "mac.h"
66
67 static void mac_startup(void);
68 static void mac_eventloop(void);
69 #pragma noreturn (mac_eventloop)
70 static void mac_event(EventRecord *);
71 static void mac_contentclick(WindowPtr, EventRecord *);
72 static void mac_growwindow(WindowPtr, EventRecord *);
73 static void mac_activatewindow(WindowPtr, EventRecord *);
74 static void mac_suspendresume(EventRecord *);
75 static void mac_updatewindow(WindowPtr);
76 static void mac_keypress(EventRecord *);
77 static int mac_windowtype(WindowPtr);
78 static void mac_menucommand(long);
79 static void mac_adjustcursor(RgnHandle);
80 static void mac_adjustmenus(void);
81 static void mac_closewindow(WindowPtr);
82 static void mac_zoomwindow(WindowPtr, short);
83 #pragma noreturn (cleanup_exit)
84
85 struct mac_windows {
86     WindowPtr about;
87     WindowPtr licence;
88 };
89
90 struct mac_windows windows;
91 int borednow;
92 struct mac_gestalts mac_gestalts;
93
94 int main (int argc, char **argv) {
95
96     mac_startup();
97     mac_eventloop();
98 }
99
100 #pragma noreturn (main)
101
102 static void mac_startup(void) {
103     Handle menuBar;
104     TECInfoHandle ti;
105
106 #if !TARGET_API_MAC_CARBON
107     /* Init Memory Manager */
108     MaxApplZone();
109     /* Init QuickDraw */
110     InitGraf(&qd.thePort);
111     /* Init Font Manager */
112     InitFonts();
113     /* Init Window Manager */
114     InitWindows();
115     /* Init Menu Manager */
116     InitMenus();
117     /* Init TextEdit */
118     TEInit();
119     /* Init Dialog Manager */
120     InitDialogs(NULL);
121 #endif
122     
123     /* Get base system version (only used if there's no better selector) */
124     if (Gestalt(gestaltSystemVersion, &mac_gestalts.sysvers) != noErr ||
125         (mac_gestalts.sysvers &= 0xffff) < 0x700)
126         fatalbox("PuTTYgen requires System 7 or newer");
127     /* Find out if we've got Color Quickdraw */
128     if (Gestalt(gestaltQuickdrawVersion, &mac_gestalts.qdvers) != noErr)
129         mac_gestalts.qdvers = gestaltOriginalQD;
130     /* ... and the Appearance Manager? */
131     if (Gestalt(gestaltAppearanceVersion, &mac_gestalts.apprvers) != noErr)
132         if (Gestalt(gestaltAppearanceAttr, NULL) == noErr)
133             mac_gestalts.apprvers = 0x0100;
134         else
135             mac_gestalts.apprvers = 0;
136 #if TARGET_RT_MAC_CFM
137     /* Paranoia: Did we manage to pull in AppearanceLib? */
138     if (&RegisterAppearanceClient == kUnresolvedCFragSymbolAddress)
139         mac_gestalts.apprvers = 0;
140 #endif
141 #if TARGET_CPU_68K
142     mac_gestalts.cntlattr = 0;
143     mac_gestalts.windattr = 0;
144 #else
145     /* Mac OS 8.5 Control Manager (proportional scrollbars)? */
146     if (Gestalt(gestaltControlMgrAttr, &mac_gestalts.cntlattr) != noErr ||
147         &SetControlViewSize == kUnresolvedCFragSymbolAddress)
148         mac_gestalts.cntlattr = 0;
149     /* Mac OS 8.5 Window Manager? */
150     if (Gestalt(gestaltWindowMgrAttr, &mac_gestalts.windattr) != noErr ||
151         &SetWindowContentColor == kUnresolvedCFragSymbolAddress)
152         mac_gestalts.windattr = 0;
153 #endif
154     /* Text Encoding Conversion Manager? */
155     if (
156 #if TARGET_RT_MAC_CFM
157         &TECGetInfo == kUnresolvedCFragSymbolAddress ||
158 #else
159         InitializeUnicodeConverter(NULL) != noErr ||
160 #endif
161         TECGetInfo(&ti) != noErr)
162         mac_gestalts.encvvers = 0;
163     else {
164         mac_gestalts.encvvers = (*ti)->tecVersion;
165         mac_gestalts.uncvattr = (*ti)->tecUnicodeConverterFeatures;
166         DisposeHandle((Handle)ti);
167     }
168     /* Navigation Services? */
169     if (NavServicesAvailable())
170         mac_gestalts.navsvers = NavLibraryVersion();
171     else
172         mac_gestalts.navsvers = 0;
173
174     /* We've been tested with the Appearance Manager */
175     if (mac_gestalts.apprvers != 0)
176         RegisterAppearanceClient();
177
178     menuBar = GetNewMBar(128);
179     if (menuBar == NULL)
180         fatalbox("Unable to create menu bar.");
181     SetMenuBar(menuBar);
182     AppendResMenu(GetMenuHandle(mApple), 'DRVR');
183     mac_adjustmenus();
184     DrawMenuBar();
185     InitCursor();
186     windows.about = NULL;
187     windows.licence = NULL;
188
189     flags = FLAG_INTERACTIVE;
190
191     /* Install Apple Event handlers. */
192 #if 0
193     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
194                           NewAEEventHandlerUPP(&mac_aevt_oapp), 0, FALSE);
195     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
196                           NewAEEventHandlerUPP(&mac_aevt_odoc), 0, FALSE);
197     AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
198                           NewAEEventHandlerUPP(&mac_aevt_pdoc), 0, FALSE);
199 #endif
200     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
201                           NewAEEventHandlerUPP(&mac_aevt_quit), 0, FALSE);
202 }
203
204 static void mac_eventloop(void) {
205     Boolean gotevent;
206     EventRecord event;
207     RgnHandle cursrgn;
208     Point mousenow, mousethen;
209     KeyState *ks;
210     WindowPtr front;
211
212     cursrgn = NewRgn();
213     GetMouse(&mousethen);
214     for (;;) {
215         mac_adjustcursor(cursrgn);
216         gotevent = WaitNextEvent(everyEvent, &event, LONG_MAX, cursrgn);
217         mac_adjustcursor(cursrgn);
218         front = mac_frontwindow();
219         if (front != NULL) {
220             ks = mac_windowkey(front);
221             if (ks->collecting_entropy) {
222                 GetMouse(&mousenow);
223                 if (mousenow.h != mousethen.h || mousenow.v != mousethen.v) {
224                     ks->entropy[ks->entropy_got++] = *(unsigned *)&mousenow;
225                     ks->entropy[ks->entropy_got++] = TickCount();
226                     if (ks->entropy_got >= ks->entropy_required)
227                         ks->collecting_entropy = 0;
228                     SetControlValue(ks->progress, ks->entropy_got);
229                     mousethen = mousenow;
230                 }
231                 SetEmptyRgn(cursrgn);
232             }
233         }
234             
235         if (gotevent)
236             mac_event(&event);
237         if (borednow)
238             cleanup_exit(0);
239     }
240     DisposeRgn(cursrgn);
241 }
242
243 static void mac_event(EventRecord *event) {
244     short part;
245     WindowPtr window;
246
247     switch (event->what) {
248       case mouseDown:
249         part = FindWindow(event->where, &window);
250         switch (part) {
251           case inMenuBar:
252             mac_adjustmenus();
253             mac_menucommand(MenuSelect(event->where));
254             break;
255 #if !TARGET_API_MAC_CARBON
256           case inSysWindow:
257             SystemClick(event, window);
258             break;
259 #endif
260           case inContent:
261             if (window != FrontWindow())
262                 /* XXX: check for movable modal dboxes? */
263                 SelectWindow(window);
264             else
265                 mac_contentclick(window, event);
266             break;
267           case inGoAway:
268             if (TrackGoAway(window, event->where))
269                 mac_closewindow(window);
270             break;
271           case inDrag:
272             /* XXX: moveable modal check? */
273 #if TARGET_API_MAC_CARBON
274             {
275                 BitMap screenBits;
276
277                 GetQDGlobalsScreenBits(&screenBits);
278                 DragWindow(window, event->where, &screenBits.bounds);
279             }
280 #else
281             DragWindow(window, event->where, &qd.screenBits.bounds);
282 #endif
283             break;
284           case inGrow:
285             mac_growwindow(window, event);
286             break;
287           case inZoomIn:
288           case inZoomOut:
289             if (TrackBox(window, event->where, part))
290                 mac_zoomwindow(window, part);
291             break;
292         }
293         break;
294       case keyDown:
295       case autoKey:
296         mac_keypress(event);
297         break;
298       case activateEvt:
299         mac_activatewindow((WindowPtr)event->message, event);
300         break;
301       case updateEvt:
302         mac_updatewindow((WindowPtr)event->message);
303         break;
304 #if !TARGET_API_MAC_CARBON
305       case diskEvt:
306         if (HiWord(event->message) != noErr) {
307             Point pt;
308
309             SetPt(&pt, 120, 120);
310             DIBadMount(pt, event->message);
311         }
312         break;
313 #endif
314       case osEvt:
315         switch ((event->message & osEvtMessageMask) >> 24) {
316           case suspendResumeMessage:
317             mac_suspendresume(event);
318             break;
319         }
320         break;
321       case kHighLevelEvent:
322         AEProcessAppleEvent(event); /* errors? */
323         break;
324     }
325 }
326
327 static void mac_contentclick(WindowPtr window, EventRecord *event)
328 {
329
330     if (mac_wininfo(window)->click != NULL)
331         (*mac_wininfo(window)->click)(window, event);
332 }
333
334 static void mac_growwindow(WindowPtr window, EventRecord *event)
335 {
336
337     if (mac_wininfo(window)->grow != NULL)
338         (*mac_wininfo(window)->grow)(window, event);
339 }
340
341 static void mac_activatewindow(WindowPtr window, EventRecord *event)
342 {
343
344     mac_adjustmenus();
345     if (mac_wininfo(window)->activate != NULL)
346         (*mac_wininfo(window)->activate)(window, event);
347 }
348
349 static void mac_updatewindow(WindowPtr window)
350 {
351
352     if (mac_wininfo(window)->update != NULL)
353         (*mac_wininfo(window)->update)(window);
354 }
355
356 /*
357  * Work out what kind of window we're dealing with.
358  */
359 static int mac_windowtype(WindowPtr window)
360 {
361
362 #if !TARGET_API_MAC_CARBON
363     if (GetWindowKind(window) < 0)
364         return wDA;
365 #endif
366     return ((WinInfo *)GetWRefCon(window))->wtype;
367 }
368
369 /*
370  * Handle a key press
371  */
372 static void mac_keypress(EventRecord *event)
373 {
374     WindowPtr window;
375
376     window = FrontWindow();
377     if (event->what == keyDown && (event->modifiers & cmdKey)) {
378         mac_adjustmenus();
379         mac_menucommand(MenuKey(event->message & charCodeMask));
380     } else {
381         if (mac_wininfo(window)->key != NULL)
382             (*mac_wininfo(window)->key)(window, event);
383     }       
384 }
385
386 static void mac_menucommand(long result)
387 {
388     short menu, item;
389     WindowPtr window;
390 #if !TARGET_API_MAC_CARBON
391     Str255 da;
392 #endif
393
394     menu = HiWord(result);
395     item = LoWord(result);
396     window = FrontWindow();
397     /* Things which do the same whatever window we're in. */
398     switch (menu) {
399       case mApple:
400         switch (item) {
401           case iAbout:
402             mac_openabout();
403             goto done;
404 #if !TARGET_API_MAC_CARBON
405           default:
406             GetMenuItemText(GetMenuHandle(mApple), item, da);
407             OpenDeskAcc(da);
408             goto done;
409 #endif
410         }
411         break;
412       case mFile:
413         switch (item) {
414           case iNew:
415             mac_newkey();
416             goto done;
417           case iClose:
418             mac_closewindow(window);
419             goto done;
420           case iQuit:
421             cleanup_exit(0);
422             goto done;
423         }
424         break;
425     }
426     /* If we get here, handling is up to window-specific code. */
427     if (mac_wininfo(window)->menu != NULL)
428         (*mac_wininfo(window)->menu)(window, menu, item);
429
430   done:
431     HiliteMenu(0);
432 }
433
434 static void mac_closewindow(WindowPtr window)
435 {
436
437     switch (mac_windowtype(window)) {
438 #if !TARGET_API_MAC_CARBON
439       case wDA:
440         CloseDeskAcc(GetWindowKind(window));
441         break;
442 #endif
443       default:
444         if (mac_wininfo(window)->close != NULL)
445             (*mac_wininfo(window)->close)(window);
446     }
447 }
448
449 static void mac_suspendresume(EventRecord *event)
450 {
451     WindowPtr front;
452     EventRecord fakeevent;
453
454     /*
455      * We're called either before we're suspended or after we're
456      * resumed, so we're the front application at this point.
457      */
458     front = FrontWindow();
459     if (front != NULL) {
460         fakeevent.what = activateEvt;
461         fakeevent.message = (UInt32)front;
462         fakeevent.when = event->when;
463         fakeevent.where = event->where;
464         fakeevent.modifiers =
465             (event->message & resumeFlag) ? activeFlag : 0;
466         mac_activatewindow(front, &fakeevent);
467     }
468 }
469
470 static void mac_zoomwindow(WindowPtr window, short part) {
471
472     /* FIXME: do something */
473 }
474
475 /*
476  * Make the menus look right before the user gets to see them.
477  */
478 #if TARGET_API_MAC_CARBON
479 #define EnableItem EnableMenuItem
480 #define DisableItem DisableMenuItem
481 #endif
482 static void mac_adjustmenus(void) {
483     WindowPtr window;
484     MenuHandle menu;
485
486     window = FrontWindow();
487     menu = GetMenuHandle(mApple);
488     EnableItem(menu, 0);
489     EnableItem(menu, iAbout);
490
491     menu = GetMenuHandle(mFile);
492     EnableItem(menu, 0);
493     EnableItem(menu, iNew);
494     if (window != NULL)
495         EnableItem(menu, iClose);
496     else
497         DisableItem(menu, iClose);
498     EnableItem(menu, iQuit);
499
500     if (mac_wininfo(window)->adjustmenus != NULL)
501         (*mac_wininfo(window)->adjustmenus)(window);
502     else {
503         DisableItem(menu, iSave);
504         DisableItem(menu, iSaveAs);
505         menu = GetMenuHandle(mEdit);
506         DisableItem(menu, 0);
507         menu = GetMenuHandle(mWindow);
508         DisableItem(menu, 0); /* Until we get more than 1 item on it. */
509     }
510     DrawMenuBar();
511 }
512
513 /*
514  * Make sure the right cursor's being displayed.
515  */
516 static void mac_adjustcursor(RgnHandle cursrgn)
517 {
518     Point mouse;
519     WindowPtr window, front;
520     short part;
521 #if TARGET_API_MAC_CARBON
522     Cursor arrow;
523     RgnHandle visrgn;
524 #endif
525
526     GetMouse(&mouse);
527     LocalToGlobal(&mouse);
528     part = FindWindow(mouse, &window);
529     front = FrontWindow();
530     if (part != inContent || window == NULL || window != front) {
531         /* Cursor isn't in the front window, so switch to arrow */
532 #if TARGET_API_MAC_CARBON
533         GetQDGlobalsArrow(&arrow);
534         SetCursor(&arrow);
535 #else
536         SetCursor(&qd.arrow);
537 #endif
538         SetRectRgn(cursrgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
539         if (front != NULL) {
540 #if TARGET_API_MAC_CARBON
541             visrgn = NewRgn();
542             GetPortVisibleRegion(GetWindowPort(front), visrgn);
543             DiffRgn(cursrgn, visrgn, cursrgn);
544             DisposeRgn(visrgn);
545 #else
546             DiffRgn(cursrgn, front->visRgn, cursrgn);
547 #endif
548         }
549     } else {
550         if (mac_wininfo(window)->adjustcursor != NULL)
551             (*mac_wininfo(window)->adjustcursor)(window, mouse, cursrgn);
552         else {
553 #if TARGET_API_MAC_CARBON
554             GetQDGlobalsArrow(&arrow);
555             SetCursor(&arrow);
556             GetPortVisibleRegion(GetWindowPort(window), cursrgn);
557 #else
558             SetCursor(&qd.arrow);
559             CopyRgn(window->visRgn, cursrgn);
560 #endif
561         }
562     }
563 }
564
565 pascal OSErr mac_aevt_quit(const AppleEvent *req, AppleEvent *reply,
566                                   long refcon)
567 {
568     DescType type;
569     Size size;
570
571     if (AEGetAttributePtr(req, keyMissedKeywordAttr, typeWildCard,
572                           &type, NULL, 0, &size) == noErr)
573         return errAEParamMissed;
574
575     borednow = 1;
576     return noErr;
577 }
578
579 void cleanup_exit(int status)
580 {
581
582 #if !TARGET_RT_MAC_CFM
583     if (mac_gestalts.encvvers != 0)
584         TerminateUnicodeConverter();
585 #endif
586     exit(status);
587 }
588
589 /*
590  * Local Variables:
591  * c-file-style: "simon"
592  * End:
593  */