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