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