]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - mac.c
sunc with reality
[PuTTY.git] / mac.c
1 /* $Id: mac.c,v 1.1.2.26 1999/08/02 22:32:38 ben Exp $ */
2 /*
3  * Copyright (c) 1999 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  * mac.c -- miscellaneous Mac-specific routines
29  */
30
31 #include <MacTypes.h>
32 #include <Quickdraw.h>
33 #include <Fonts.h>
34 #include <MacWindows.h>
35 #include <Menus.h>
36 #include <TextEdit.h>
37 #include <Appearance.h>
38 #include <CodeFragments.h>
39 #include <Dialogs.h>
40 #include <Devices.h>
41 #include <DiskInit.h>
42 #include <Gestalt.h>
43 #include <Resources.h>
44 #include <ToolUtils.h>
45
46 #include <assert.h>
47 #include <limits.h>
48 #include <stdarg.h>
49 #include <stdlib.h>             /* putty.h needs size_t */
50 #include <stdio.h>              /* for vsprintf */
51
52 #define PUTTY_DO_GLOBALS
53
54 #include "macresid.h"
55 #include "putty.h"
56 #include "mac.h"
57
58 QDGlobals qd;
59
60 static int cold = 1;
61 struct mac_gestalts mac_gestalts;
62
63 static void mac_startup(void);
64 static void mac_eventloop(void);
65 #pragma noreturn (mac_eventloop)
66 static void mac_event(EventRecord *);
67 static void mac_contentclick(WindowPtr, EventRecord *);
68 static void mac_growwindow(WindowPtr, EventRecord *);
69 static void mac_activatewindow(WindowPtr, EventRecord *);
70 static void mac_activateabout(WindowPtr, EventRecord *);
71 static void mac_updatewindow(WindowPtr);
72 static void mac_keypress(EventRecord *);
73 static int mac_windowtype(WindowPtr);
74 static void mac_menucommand(long);
75 static void mac_openabout(void);
76 static void mac_adjustcursor(RgnHandle);
77 static void mac_adjustmenus(void);
78 static void mac_closewindow(WindowPtr);
79 static void mac_zoomwindow(WindowPtr, short);
80 static void mac_shutdown(void);
81 #pragma noreturn (mac_shutdown)
82
83 struct mac_windows {
84     WindowPtr about;
85     WindowPtr licence;
86 };
87
88 struct mac_windows windows;
89
90 int main (int argc, char **argv) {
91
92     mac_startup();
93     mac_eventloop();
94 }
95
96 #pragma noreturn (main)
97
98 static void mac_startup(void) {
99     Handle menuBar;
100
101     /* Init QuickDraw */
102     InitGraf(&qd.thePort);
103     /* Init Font Manager */
104     InitFonts();
105     /* Init Window Manager */
106     InitWindows();
107     /* Init Menu Manager */
108     InitMenus();
109     /* Init TextEdit */
110     TEInit();
111     /* Init Dialog Manager */
112     InitDialogs(nil);
113     cold = 0;
114     
115     /* Find out if we've got Color Quickdraw */
116     if (Gestalt(gestaltQuickdrawVersion, &mac_gestalts.qdvers) != noErr)
117         mac_gestalts.qdvers = gestaltOriginalQD;
118     /* ... and the Appearance Manager? */
119     if (Gestalt(gestaltAppearanceVersion, &mac_gestalts.apprvers) != noErr)
120         if (Gestalt(gestaltAppearanceAttr, NULL) == noErr)
121             mac_gestalts.apprvers = 0x0100;
122         else
123             mac_gestalts.apprvers = 0;
124     /* Paranoia: Did we manage to pull in AppearanceLib? */
125     if (&RegisterAppearanceClient == kUnresolvedCFragSymbolAddress)
126         mac_gestalts.apprvers = 0;
127     /* Mac OS 8.5 Control Manager (proportional scrollbars)? */
128     if (Gestalt(gestaltControlMgrAttr, &mac_gestalts.cntlattr) != noErr)
129         mac_gestalts.cntlattr = 0;
130     /* Mac OS 8.5 Window Manager? */
131     if (Gestalt(gestaltWindowMgrAttr, &mac_gestalts.windattr) != noErr)
132         mac_gestalts.windattr = 0;
133
134     /* We've been tested with the Appearance Manager */
135     if (mac_gestalts.apprvers != 0)
136         RegisterAppearanceClient();
137     
138     menuBar = GetNewMBar(128);
139     if (menuBar == NULL)
140         fatalbox("Unable to create menu bar.");
141     SetMenuBar(menuBar);
142     AppendResMenu(GetMenuHandle(mApple), 'DRVR');
143     mac_adjustmenus();
144     DrawMenuBar();
145     InitCursor();
146     windows.about = NULL;
147     windows.licence = NULL;
148
149     /* Initialise networking */
150 #ifdef WITH_OPENTRANSPORT
151     if ((*otpt_stack.init)() == 0)
152         net_stack = &otpt_stack;
153     else 
154 #endif
155 #ifdef WITH_MACTCP
156     if ((*mtcp_stack.init)() == 0)
157         net_stack = &mtcp_stack;
158     else
159 #endif
160         fatalbox("No useful TCP/IP stack found");
161
162         
163
164 }
165
166 static void mac_eventloop(void) {
167     Boolean gotevent;
168     EventRecord event;
169     RgnHandle cursrgn;
170
171     cursrgn = NewRgn();
172     for (;;) {
173         mac_adjustcursor(cursrgn);
174         gotevent = WaitNextEvent(everyEvent, &event, LONG_MAX, cursrgn);
175         mac_adjustcursor(cursrgn);
176         if (gotevent)
177             mac_event(&event);
178         net_poll();
179     }
180     DisposeRgn(cursrgn);
181 }
182
183 static void mac_event(EventRecord *event) {
184     short part;
185     WindowPtr window;
186     Point pt;
187
188     switch (event->what) {
189       case mouseDown:
190         part = FindWindow(event->where, &window);
191         switch (part) {
192           case inMenuBar:
193             mac_adjustmenus();
194             mac_menucommand(MenuSelect(event->where));
195             break;
196           case inSysWindow:
197             SystemClick(event, window);
198             break;
199           case inContent:
200             if (window != FrontWindow())
201                 /* XXX: check for movable modal dboxes? */
202                 SelectWindow(window);
203             else
204                 mac_contentclick(window, event);
205             break;
206           case inGoAway:
207             if (TrackGoAway(window, event->where))
208                 mac_closewindow(window);
209             break;
210           case inDrag:
211             /* XXX: moveable modal check? */
212             DragWindow(window, event->where, &qd.screenBits.bounds);
213             break;
214           case inGrow:
215             mac_growwindow(window, event);
216             break;
217           case inZoomIn:
218           case inZoomOut:
219             if (TrackBox(window, event->where, part))
220                 mac_zoomwindow(window, part);
221             break;
222         }
223         break;
224       case keyDown:
225       case autoKey:
226         mac_keypress(event);
227         break;
228       case activateEvt:
229         mac_activatewindow((WindowPtr)event->message, event);
230         break;
231       case updateEvt:
232         mac_updatewindow((WindowPtr)event->message);
233         break;
234       case diskEvt:
235         if (HiWord(event->message) != noErr) {
236             SetPt(&pt, 120, 120);
237             DIBadMount(pt, event->message);
238         }
239         break;
240     }
241 }
242
243 static void mac_contentclick(WindowPtr window, EventRecord *event) {
244     short item;
245
246     switch (mac_windowtype(window)) {
247       case wTerminal:
248         mac_clickterm(window, event);
249         break;
250       case wAbout:
251         if (DialogSelect(event, &(DialogPtr)window, &item))
252             switch (item) {
253               case wiAboutLicence:
254                 /* XXX: Do something */
255                 break;
256             }
257         break;
258     }
259 }
260
261 static void mac_growwindow(WindowPtr window, EventRecord *event) {
262
263     switch (mac_windowtype(window)) {
264       case wTerminal:
265         mac_growterm(window, event);
266     }
267 }
268
269 static void mac_activatewindow(WindowPtr window, EventRecord *event) {
270     int active;
271
272     active = (event->modifiers & activeFlag) != 0;
273     mac_adjustmenus();
274     switch (mac_windowtype(window)) {
275       case wTerminal:
276         mac_activateterm(window, active);
277         break;
278       case wAbout:
279         mac_activateabout(window, event);
280         break;
281     }
282 }
283
284 static void mac_activateabout(WindowPtr window, EventRecord *event) {
285     DialogItemType itemtype;
286     Handle itemhandle;
287     short item;
288     Rect itemrect;
289     int active;
290
291     active = (event->modifiers & activeFlag) != 0;
292     GetDialogItem(window, wiAboutLicence, &itemtype, &itemhandle, &itemrect);
293     HiliteControl((ControlHandle)itemhandle, active ? 0 : 255);
294     DialogSelect(event, &window, &item);
295 }
296
297 static void mac_updatewindow(WindowPtr window) {
298
299     switch (mac_windowtype(window)) {
300       case wTerminal:
301         mac_updateterm(window);
302         break;
303       case wAbout:
304         BeginUpdate(window);
305         UpdateDialog(window, window->visRgn);
306         EndUpdate(window);
307         break;
308       case wLicence:
309         /* Do something */
310         break;
311     }
312 }
313
314 /*
315  * Work out what kind of window we're dealing with.
316  * Concept shamelessly nicked from SurfWriter.
317  */
318 static int mac_windowtype(WindowPtr window) {
319     int kind;
320
321     if (window == NULL)
322         return wNone;
323     kind = ((WindowPeek)window)->windowKind;
324     if (kind < 0)
325         return wDA;
326     if (GetWVariant(window) == zoomDocProc)
327         return wTerminal;
328     return GetWRefCon(window);
329 }
330
331 /*
332  * Handle a key press
333  */
334 static void mac_keypress(EventRecord *event) {
335     WindowPtr window;
336
337     window = FrontWindow();
338     /*
339      * Check for a command-key combination, but ignore it if it counts
340      * as a meta-key combination and we're in a terminal window.
341      */
342     if (event->what == keyDown && (event->modifiers & cmdKey) /*&&
343         !((event->modifiers & cfg.meta_modifiers) == cfg.meta_modifiers &&
344             mac_windowtype(window) == wTerminal)*/) {
345         mac_adjustmenus();
346         mac_menucommand(MenuKey(event->message & charCodeMask));
347     } else {
348         switch (mac_windowtype(window)) {
349           case wTerminal:
350             mac_keyterm(window, event);
351             break;
352         }
353     }       
354 }
355
356 static void mac_menucommand(long result) {
357     short menu, item;
358     Str255 da;
359     WindowPtr window;
360
361     menu = HiWord(result);
362     item = LoWord(result);
363     window = FrontWindow();
364     /* Things which do the same whatever window we're in. */
365     switch (menu) {
366       case mApple:
367         switch (item) {
368           case iAbout:
369             mac_openabout();
370             goto done;
371           default:
372             GetMenuItemText(GetMenuHandle(mApple), item, da);
373             OpenDeskAcc(da);
374             goto done;
375         }
376         break;
377       case mFile:
378         switch (item) {
379           case iNew:
380             mac_newsession();
381             goto done;
382           case iClose:
383             mac_closewindow(window);
384             goto done;
385           case iQuit:
386             mac_shutdown();
387             goto done;
388         }
389         break;
390     }
391     /* If we get here, handling is up to window-specific code. */
392     switch (mac_windowtype(window)) {
393       case wTerminal:
394         mac_menuterm(window, menu, item);
395         break;
396     }
397   done:
398     HiliteMenu(0);
399 }
400
401 static void mac_openabout(void) {
402     DialogItemType itemtype;
403     Handle item;
404     VersRecHndl vers;
405     Rect box;
406     StringPtr longvers;
407
408     if (windows.about)
409         SelectWindow(windows.about);
410     else {
411         windows.about = GetNewDialog(wAbout, NULL, (WindowPtr)-1);
412         /* XXX check we're using the right resource file? */
413         vers = (VersRecHndl)GetResource('vers', 1);
414         assert(vers != NULL && *vers != NULL);
415         longvers = (*vers)->shortVersion + (*vers)->shortVersion[0] + 1;
416         GetDialogItem(windows.about, wiAboutVersion, &itemtype, &item, &box);
417         assert(itemtype & kStaticTextDialogItem);
418         SetDialogItemText(item, longvers);
419         ShowWindow(windows.about);
420     }
421 }
422
423 static void mac_closewindow(WindowPtr window) {
424
425     switch (mac_windowtype(window)) {
426       case wDA:
427         CloseDeskAcc(((WindowPeek)window)->windowKind);
428         break;
429       case wTerminal:
430         /* FIXME: end session and stuff */
431         break;
432       case wAbout:
433         windows.about = NULL;
434         CloseWindow(window);
435         break;
436       default:
437         CloseWindow(window);
438         break;
439     }
440 }
441
442 static void mac_zoomwindow(WindowPtr window, short part) {
443
444     /* FIXME: do something */
445 }
446
447 /*
448  * Make the menus look right before the user gets to see them.
449  */
450 static void mac_adjustmenus(void) {
451     WindowPtr window;
452     MenuHandle menu;
453
454     window = FrontWindow();
455     menu = GetMenuHandle(mApple);
456     EnableItem(menu, 0);
457     EnableItem(menu, iAbout);
458
459     menu = GetMenuHandle(mFile);
460     EnableItem(menu, 0);
461     EnableItem(menu, iNew);
462     if (window != NULL)
463         EnableItem(menu, iClose);
464     else
465         DisableItem(menu, iClose);
466     EnableItem(menu, iQuit);
467
468     switch (mac_windowtype(window)) {
469       case wTerminal:
470         mac_adjusttermmenus(window);
471         break;
472       default:
473         menu = GetMenuHandle(mEdit);
474         DisableItem(menu, 0);
475         break;
476     }
477     DrawMenuBar();
478 }
479
480 /*
481  * Make sure the right cursor's being displayed.
482  */
483 static void mac_adjustcursor(RgnHandle cursrgn) {
484     Point mouse;
485     WindowPtr window, front;
486     short part;
487
488     GetMouse(&mouse);
489     LocalToGlobal(&mouse);
490     part = FindWindow(mouse, &window);
491     front = FrontWindow();
492     if (part != inContent || window == NULL || window != front) {
493         /* Cursor isn't in the front window, so switch to arrow */
494         SetCursor(&qd.arrow);
495         SetRectRgn(cursrgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
496         if (front != NULL)
497             DiffRgn(cursrgn, front->visRgn, cursrgn);
498     } else {
499         switch (mac_windowtype(window)) {
500           case wTerminal:
501             mac_adjusttermcursor(window, mouse, cursrgn);
502             break;
503           default:
504             SetCursor(&qd.arrow);
505             CopyRgn(window->visRgn, cursrgn);
506             break;
507         }
508     }
509 }
510
511 static void mac_shutdown(void) {
512
513     net_shutdown();
514     exit(0);
515 }
516
517 void fatalbox(const char *fmt, ...) {
518     va_list ap;
519     Str255 stuff;
520     
521     va_start(ap, fmt);
522     /* We'd like stuff to be a Pascal string */
523     stuff[0] = vsprintf((char *)(&stuff[1]), fmt, ap);
524     va_end(ap);
525     ParamText(stuff, NULL, NULL, NULL);
526     StopAlert(128, nil);
527     exit(1);
528 }
529
530 /*
531  * Local Variables:
532  * c-file-style: "simon"
533  * End:
534  */