]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - mac/mac.c
Remove unwanted underscore.
[PuTTY.git] / mac / mac.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  * mac.c -- miscellaneous Mac-specific routines
29  */
30
31 #include <MacTypes.h>
32 #include <AEDataModel.h>
33 #include <AppleEvents.h>
34 #include <Controls.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 "macresid.h"
63 #include "putty.h"
64 #include "ssh.h"
65 #include "terminal.h"
66 #include "mac.h"
67
68 Session *sesslist;
69
70 static int cold = 1;
71 static int borednow = FALSE;
72 struct mac_gestalts mac_gestalts;
73 UInt32 sleeptime;
74
75 static void mac_startup(void);
76 static void mac_eventloop(void);
77 #pragma noreturn (mac_eventloop)
78 static void mac_event(EventRecord *);
79 static void mac_contentclick(WindowPtr, EventRecord *);
80 static void mac_growwindow(WindowPtr, EventRecord *);
81 static void mac_activatewindow(WindowPtr, EventRecord *);
82 static void mac_suspendresume(EventRecord *);
83 static void mac_activateabout(WindowPtr, EventRecord *);
84 static void mac_updatewindow(WindowPtr);
85 static void mac_updatelicence(WindowPtr);
86 static void mac_keypress(EventRecord *);
87 static int mac_windowtype(WindowPtr);
88 static void mac_menucommand(long);
89 static void mac_openlicence(void);
90 static void mac_adjustcursor(RgnHandle);
91 static void mac_adjustmenus(void);
92 static void mac_closewindow(WindowPtr);
93 static void mac_zoomwindow(WindowPtr, short);
94 #pragma noreturn (cleanup_exit)
95
96 struct mac_windows {
97     WindowPtr about;
98     WindowPtr licence;
99 };
100
101 struct mac_windows windows;
102
103 int main (int argc, char **argv) {
104
105     mac_startup();
106     mac_eventloop();
107 }
108
109 #pragma noreturn (main)
110
111 static void mac_startup(void) {
112     Handle menuBar;
113     TECInfoHandle ti;
114
115 #if !TARGET_API_MAC_CARBON
116     /* Init Memory Manager */
117     MaxApplZone();
118     /* Init QuickDraw */
119     InitGraf(&qd.thePort);
120     /* Init Font Manager */
121     InitFonts();
122     /* Init Window Manager */
123     InitWindows();
124     /* Init Menu Manager */
125     InitMenus();
126     /* Init TextEdit */
127     TEInit();
128     /* Init Dialog Manager */
129     InitDialogs(NULL);
130 #endif
131     cold = 0;
132     
133     /* Get base system version (only used if there's no better selector) */
134     if (Gestalt(gestaltSystemVersion, &mac_gestalts.sysvers) != noErr ||
135         (mac_gestalts.sysvers &= 0xffff) < 0x700)
136         fatalbox("PuTTY requires System 7 or newer");
137     /* Find out if we've got Color Quickdraw */
138     if (Gestalt(gestaltQuickdrawVersion, &mac_gestalts.qdvers) != noErr)
139         mac_gestalts.qdvers = gestaltOriginalQD;
140     /* ... and the Appearance Manager? */
141     if (Gestalt(gestaltAppearanceVersion, &mac_gestalts.apprvers) != noErr)
142         if (Gestalt(gestaltAppearanceAttr, NULL) == noErr)
143             mac_gestalts.apprvers = 0x0100;
144         else
145             mac_gestalts.apprvers = 0;
146 #if TARGET_RT_MAC_CFM
147     /* Paranoia: Did we manage to pull in AppearanceLib? */
148     if (&RegisterAppearanceClient == kUnresolvedCFragSymbolAddress)
149         mac_gestalts.apprvers = 0;
150 #endif
151 #if TARGET_CPU_68K
152     mac_gestalts.cntlattr = 0;
153     mac_gestalts.windattr = 0;
154 #else
155     /* Mac OS 8.5 Control Manager (proportional scrollbars)? */
156     if (Gestalt(gestaltControlMgrAttr, &mac_gestalts.cntlattr) != noErr ||
157         &SetControlViewSize == kUnresolvedCFragSymbolAddress)
158         mac_gestalts.cntlattr = 0;
159     /* Mac OS 8.5 Window Manager? */
160     if (Gestalt(gestaltWindowMgrAttr, &mac_gestalts.windattr) != noErr ||
161         &SetWindowContentColor == kUnresolvedCFragSymbolAddress)
162         mac_gestalts.windattr = 0;
163     /* Mac OS 8.5 Menu Manager? */
164     if (Gestalt(gestaltMenuMgrAttr, &mac_gestalts.menuattr) != noErr)
165         mac_gestalts.menuattr = 0;
166 #endif
167     /* Text Encoding Conversion Manager? */
168     if (
169 #if TARGET_RT_MAC_CFM
170         &TECGetInfo == kUnresolvedCFragSymbolAddress ||
171 #else
172         InitializeUnicodeConverter(NULL) != noErr ||
173 #endif
174         TECGetInfo(&ti) != noErr)
175         mac_gestalts.encvvers = 0;
176     else {
177         mac_gestalts.encvvers = (*ti)->tecVersion;
178         mac_gestalts.uncvattr = (*ti)->tecUnicodeConverterFeatures;
179         DisposeHandle((Handle)ti);
180     }
181     /* Navigation Services? */
182     if (NavServicesAvailable())
183         mac_gestalts.navsvers = NavLibraryVersion();
184     else
185         mac_gestalts.navsvers = 0;
186
187     sk_init();
188
189     /* We've been tested with the Appearance Manager */
190     if (mac_gestalts.apprvers != 0)
191         RegisterAppearanceClient();
192
193     menuBar = GetNewMBar(128);
194     if (menuBar == NULL)
195         fatalbox("Unable to create menu bar.");
196     SetMenuBar(menuBar);
197     AppendResMenu(GetMenuHandle(mApple), 'DRVR');
198     if (mac_gestalts.menuattr & gestaltMenuMgrAquaLayoutMask) {
199         DeleteMenuItem(GetMenuHandle(mFile), iQuit);
200         /* Also delete the separator above the Quit item. */
201         DeleteMenuItem(GetMenuHandle(mFile), iQuit - 1);
202     }
203     mac_adjustmenus();
204     DrawMenuBar();
205     InitCursor();
206     windows.about = NULL;
207     windows.licence = NULL;
208
209     default_protocol = be_default_protocol;
210     /* Find the appropriate default port. */
211     {
212         int i;
213         default_port = 0; /* illegal */
214         for (i = 0; backends[i].backend != NULL; i++)
215             if (backends[i].protocol == default_protocol) {
216                 default_port = backends[i].backend->default_port;
217                 break;
218             }
219     }
220     flags = FLAG_INTERACTIVE;
221
222 #if !TARGET_API_MAC_CARBON
223     {
224         short vol;
225         long dirid;
226
227         /* Set the default directory for loading and saving settings. */
228         /* XXX Should we create it? */
229         if (get_session_dir(FALSE, &vol, &dirid) == noErr) {
230             LMSetSFSaveDisk(-vol);
231             LMSetCurDirStore(dirid);
232         }
233     }
234 #endif
235
236     /* Install Apple Event handlers. */
237     AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
238                           NewAEEventHandlerUPP(&mac_aevt_oapp), 0, FALSE);
239     AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
240                           NewAEEventHandlerUPP(&mac_aevt_odoc), 0, FALSE);
241     AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
242                           NewAEEventHandlerUPP(&mac_aevt_pdoc), 0, FALSE);
243     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
244                           NewAEEventHandlerUPP(&mac_aevt_quit), 0, FALSE);
245 }
246
247 static void mac_eventloop(void) {
248     Boolean gotevent;
249     EventRecord event;
250     RgnHandle cursrgn;
251
252     cursrgn = NewRgn();
253     sleeptime = 0;
254     for (;;) {
255         mac_adjustcursor(cursrgn);
256         gotevent = WaitNextEvent(everyEvent, &event, sleeptime, cursrgn);
257         /*
258          * XXX For now, limit sleep time to 1/10 s to work around
259          * wake-before-sleep race in MacTCP code.
260          */
261         sleeptime = 6;
262         mac_adjustcursor(cursrgn);
263         if (gotevent) {
264             /* Ensure we get a null event when the real ones run out. */
265             sleeptime = 0;
266             mac_event(&event);
267             if (borednow)
268                 cleanup_exit(0);
269         }
270         sk_poll();
271         if (!gotevent)
272             mac_pollterm();
273         if (mac_gestalts.apprvers >= 0x100 && mac_frontwindow() != NULL)
274             IdleControls(mac_frontwindow());
275     }
276     DisposeRgn(cursrgn);
277 }
278
279 static void mac_event(EventRecord *event) {
280     short part;
281     WindowPtr window;
282
283     switch (event->what) {
284       case mouseDown:
285         part = FindWindow(event->where, &window);
286         switch (part) {
287           case inMenuBar:
288             mac_adjustmenus();
289             mac_menucommand(MenuSelect(event->where));
290             break;
291 #if !TARGET_API_MAC_CARBON
292           case inSysWindow:
293             SystemClick(event, window);
294             break;
295 #endif
296           case inContent:
297             if (window != FrontWindow())
298                 /* XXX: check for movable modal dboxes? */
299                 SelectWindow(window);
300             else
301                 mac_contentclick(window, event);
302             break;
303           case inGoAway:
304             if (TrackGoAway(window, event->where))
305                 mac_closewindow(window);
306             break;
307           case inDrag:
308             /* XXX: moveable modal check? */
309 #if TARGET_API_MAC_CARBON
310             {
311                 BitMap screenBits;
312
313                 GetQDGlobalsScreenBits(&screenBits);
314                 DragWindow(window, event->where, &screenBits.bounds);
315             }
316 #else
317             DragWindow(window, event->where, &qd.screenBits.bounds);
318 #endif
319             break;
320           case inGrow:
321             mac_growwindow(window, event);
322             break;
323           case inZoomIn:
324           case inZoomOut:
325             if (TrackBox(window, event->where, part))
326                 mac_zoomwindow(window, part);
327             break;
328         }
329         break;
330       case keyDown:
331       case autoKey:
332         mac_keypress(event);
333         break;
334       case activateEvt:
335         mac_activatewindow((WindowPtr)event->message, event);
336         break;
337       case updateEvt:
338         mac_updatewindow((WindowPtr)event->message);
339         break;
340 #if !TARGET_API_MAC_CARBON
341       case diskEvt:
342         if (HiWord(event->message) != noErr) {
343             Point pt;
344
345             SetPt(&pt, 120, 120);
346             DIBadMount(pt, event->message);
347         }
348         break;
349 #endif
350       case osEvt:
351         switch ((event->message & osEvtMessageMask) >> 24) {
352           case suspendResumeMessage:
353             mac_suspendresume(event);
354             break;
355         }
356         break;
357       case kHighLevelEvent:
358         AEProcessAppleEvent(event); /* errors? */
359         break;
360     }
361 }
362
363 static void mac_contentclick(WindowPtr window, EventRecord *event)
364 {
365
366     if (mac_wininfo(window)->click != NULL)
367         (*mac_wininfo(window)->click)(window, event);
368 }
369
370 static void mac_growwindow(WindowPtr window, EventRecord *event)
371 {
372
373     if (mac_wininfo(window)->grow != NULL)
374         (*mac_wininfo(window)->grow)(window, event);
375 }
376
377 static void mac_activatewindow(WindowPtr window, EventRecord *event)
378 {
379
380     mac_adjustmenus();
381     if (mac_wininfo(window)->activate != NULL)
382         (*mac_wininfo(window)->activate)(window, event);
383 }
384
385 static void mac_updatewindow(WindowPtr window)
386 {
387
388     if (mac_wininfo(window)->update != NULL)
389         (*mac_wininfo(window)->update)(window);
390 }
391
392 /*
393  * Work out what kind of window we're dealing with.
394  */
395 static int mac_windowtype(WindowPtr window)
396 {
397
398 #if !TARGET_API_MAC_CARBON
399     if (GetWindowKind(window) < 0)
400         return wDA;
401 #endif
402     return ((WinInfo *)GetWRefCon(window))->wtype;
403 }
404
405 /*
406  * Handle a key press
407  */
408 static void mac_keypress(EventRecord *event) {
409     WindowPtr window;
410
411     window = mac_frontwindow();
412     /*
413      * Check for a command-key combination, but ignore it if it counts
414      * as a meta-key combination and we're in a terminal window.
415      */
416     if (event->what == keyDown && (event->modifiers & cmdKey) /*&&
417         !((event->modifiers & cfg.meta_modifiers) == cfg.meta_modifiers &&
418             mac_windowtype(window) == wTerminal)*/) {
419         mac_adjustmenus();
420         mac_menucommand(MenuKey(event->message & charCodeMask));
421     } else {
422         if (window != NULL && mac_wininfo(window)->key != NULL)
423             (*mac_wininfo(window)->key)(window, event);
424     }       
425 }
426
427 static void mac_menucommand(long result) {
428     short menu, item;
429     WindowPtr window;
430 #if !TARGET_API_MAC_CARBON
431     Str255 da;
432 #endif
433
434     menu = HiWord(result);
435     item = LoWord(result);
436     window = mac_frontwindow();
437     /* Things which do the same whatever window we're in. */
438     switch (menu) {
439       case mApple:
440         switch (item) {
441           case iAbout:
442             mac_openabout();
443             goto done;
444 #if !TARGET_API_MAC_CARBON
445           default:
446             GetMenuItemText(GetMenuHandle(mApple), item, da);
447             OpenDeskAcc(da);
448             goto done;
449 #endif
450         }
451         break;
452       case mFile:
453         switch (item) {
454           case iNew:
455             mac_newsession();
456             goto done;
457           case iOpen:
458             mac_opensession();
459             goto done;
460           case iClose:
461             mac_closewindow(window);
462             goto done;
463           case iSave:
464             mac_savesession();
465             goto done;
466           case iSaveAs:
467             mac_savesessionas();
468             goto done;
469           case iDuplicate:
470             mac_dupsession();
471             goto done;
472           case iQuit:
473             cleanup_exit(0);
474             goto done;
475         }
476         break;
477     }
478     /* If we get here, handling is up to window-specific code. */
479     if (window != NULL && mac_wininfo(window)->menu != NULL)
480         (*mac_wininfo(window)->menu)(window, menu, item);
481
482   done:
483     HiliteMenu(0);
484 }
485
486 static void mac_closewindow(WindowPtr window) {
487
488     switch (mac_windowtype(window)) {
489 #if !TARGET_API_MAC_CARBON
490       case wDA:
491         CloseDeskAcc(GetWindowKind(window));
492         break;
493 #endif
494       default:
495         if (mac_wininfo(window)->close != NULL)
496             (*mac_wininfo(window)->close)(window);
497         break;
498     }
499 }
500
501 static void mac_suspendresume(EventRecord *event)
502 {
503     WindowPtr front;
504     EventRecord fakeevent;
505
506     /*
507      * We're called either before we're suspended or after we're
508      * resumed, so we're the front application at this point.
509      */
510     front = FrontWindow();
511     if (front != NULL) {
512         fakeevent.what = activateEvt;
513         fakeevent.message = (UInt32)front;
514         fakeevent.when = event->when;
515         fakeevent.where = event->where;
516         fakeevent.modifiers =
517             (event->message & resumeFlag) ? activeFlag : 0;
518         mac_activatewindow(front, &fakeevent);
519     }
520 }
521
522 static void mac_zoomwindow(WindowPtr window, short part) {
523
524     /* FIXME: do something */
525 }
526
527 /*
528  * Make the menus look right before the user gets to see them.
529  */
530 #if TARGET_API_MAC_CARBON
531 #define EnableItem EnableMenuItem
532 #define DisableItem DisableMenuItem
533 #endif
534 static void mac_adjustmenus(void) {
535     WindowPtr window;
536     MenuHandle menu;
537
538     window = mac_frontwindow();
539     menu = GetMenuHandle(mApple);
540     EnableItem(menu, 0);
541     EnableItem(menu, iAbout);
542
543     menu = GetMenuHandle(mFile);
544     EnableItem(menu, 0);
545     EnableItem(menu, iNew);
546     if (window != NULL)
547         EnableItem(menu, iClose);
548     else
549         DisableItem(menu, iClose);
550     EnableItem(menu, iQuit);
551
552     if (window != NULL && mac_wininfo(window)->adjustmenus != NULL)
553         (*mac_wininfo(window)->adjustmenus)(window);
554     else {
555         DisableItem(menu, iSave);
556         DisableItem(menu, iSaveAs);
557         DisableItem(menu, iDuplicate);
558         menu = GetMenuHandle(mEdit);
559         DisableItem(menu, 0);
560         menu = GetMenuHandle(mWindow);
561         DisableItem(menu, 0); /* Until we get more than 1 item on it. */
562     }
563     DrawMenuBar();
564 }
565
566 /*
567  * Make sure the right cursor's being displayed.
568  */
569 static void mac_adjustcursor(RgnHandle cursrgn) {
570     Point mouse;
571     WindowPtr window, front;
572     short part;
573 #if TARGET_API_MAC_CARBON
574     Cursor arrow;
575     RgnHandle visrgn;
576 #endif
577
578     GetMouse(&mouse);
579     LocalToGlobal(&mouse);
580     part = FindWindow(mouse, &window);
581     front = FrontWindow();
582     if (part != inContent || window == NULL || window != front) {
583         /* Cursor isn't in the front window, so switch to arrow */
584 #if TARGET_API_MAC_CARBON
585         GetQDGlobalsArrow(&arrow);
586         SetCursor(&arrow);
587 #else
588         SetCursor(&qd.arrow);
589 #endif
590         SetRectRgn(cursrgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX);
591         if (front != NULL) {
592 #if TARGET_API_MAC_CARBON
593             visrgn = NewRgn();
594             GetPortVisibleRegion(GetWindowPort(front), visrgn);
595             DiffRgn(cursrgn, visrgn, cursrgn);
596             DisposeRgn(visrgn);
597 #else
598             DiffRgn(cursrgn, front->visRgn, cursrgn);
599 #endif
600         }
601     } else {
602         if (mac_wininfo(window)->adjustcursor != NULL)
603             (*mac_wininfo(window)->adjustcursor)(window, mouse, cursrgn);
604         else {
605 #if TARGET_API_MAC_CARBON
606             GetQDGlobalsArrow(&arrow);
607             SetCursor(&arrow);
608             GetPortVisibleRegion(GetWindowPort(window), cursrgn);
609 #else
610             SetCursor(&qd.arrow);
611             CopyRgn(window->visRgn, cursrgn);
612 #endif
613         }
614     }
615 }
616
617 pascal OSErr mac_aevt_quit(const AppleEvent *req, AppleEvent *reply,
618                                   long refcon)
619 {
620     DescType type;
621     Size size;
622
623     if (AEGetAttributePtr(req, keyMissedKeywordAttr, typeWildCard,
624                           &type, NULL, 0, &size) == noErr)
625         return errAEParamMissed;
626
627     borednow = 1;
628     return noErr;
629 }
630
631 void cleanup_exit(int status)
632 {
633
634 #if !TARGET_RT_MAC_CFM
635     if (mac_gestalts.encvvers != 0)
636         TerminateUnicodeConverter();
637 #endif
638     sk_cleanup();
639     exit(status);
640 }
641
642 /* This should only kill the current session, not the whole application. */
643 void connection_fatal(void *fontend, char *fmt, ...) {
644     va_list ap;
645     Str255 stuff;
646     
647     va_start(ap, fmt);
648     /* We'd like stuff to be a Pascal string */
649     stuff[0] = vsprintf((char *)(&stuff[1]), fmt, ap);
650     va_end(ap);
651     ParamText(stuff, NULL, NULL, NULL);
652     StopAlert(128, NULL);
653     cleanup_exit(1);
654 }
655
656 /* Null SSH agent client -- never finds an agent. */
657
658 int agent_exists(void)
659 {
660
661     return FALSE;
662 }
663
664 int agent_query(void *in, int inlen, void **out, int *outlen,
665                 void (*callback)(void *, void *, int), void *callback_ctx)
666 {
667
668     *out = NULL;
669     *outlen = 0;
670     return 1;
671 }
672
673 /* Temporary null routines for testing. */
674
675 void verify_ssh_host_key(void *frontend, char *host, int port, char *keytype,
676                          char *keystr, char *fingerprint)
677 {
678     Str255 stuff;
679     Session *s = frontend;
680
681     /*
682      * This function is horribly wrong.  For one thing, the alert
683      * shouldn't be modal, it should be movable modal, or a sheet in
684      * Aqua.  Also, PuTTY might be in the background, in which case we
685      * should use the Notification Manager to wake up the user.  In
686      * any case, we shouldn't hold up processing of other connections'
687      * data just because this one's waiting for the user.  It should
688      * also handle a host key cache, of course, and see the note below
689      * about closing the connection.  All in all, a bit of a mess
690      * really.
691      */
692
693     stuff[0] = sprintf((char *)(&stuff[1]),
694                        "The server's key fingerprint is: %s\n"
695                        "Continue connecting?", fingerprint);
696     ParamText(stuff, NULL, NULL, NULL);
697     if (CautionAlert(wQuestion, NULL) == 2) {
698         /*
699          * User chose "Cancel".  Unfortunately, if I tear the
700          * connection down here, Bad Things happen when I return.  I
701          * think this function should actually return something
702          * telling the SSH code to abandon the connection.
703          */
704     }
705 }
706
707 void askalg(void *frontend, const char *algtype, const char *algname)
708 {
709
710 }
711
712 void old_keyfile_warning(void)
713 {
714
715 }
716
717 FontSpec platform_default_fontspec(char const *name)
718 {
719     FontSpec ret;
720     long smfs;
721
722     if (!strcmp(name, "Font")) {
723         smfs = GetScriptVariable(smSystemScript, smScriptMonoFondSize);
724         if (smfs == 0)
725             smfs = GetScriptVariable(smRoman, smScriptMonoFondSize);
726         if (smfs != 0) {
727             GetFontName(HiWord(smfs), ret.name);
728             if (ret.name[0] == 0)
729                 memcpy(ret.name, "\pMonaco", 7);
730             ret.size = LoWord(smfs);
731         } else {
732             memcpy(ret.name, "\pMonaco", 7);
733             ret.size = 9;
734         }
735         ret.face = 0;
736     } else {
737         ret.name[0] = 0;
738     }
739
740     return ret;
741 }
742
743 Filename platform_default_filename(const char *name)
744 {
745     Filename ret;
746     if (!strcmp(name, "LogFileName"))
747         FSMakeFSSpec(0, 0, "\pputty.log", &ret.fss);
748     else
749         memset(&ret, 0, sizeof(ret));
750     return ret;
751 }
752
753 char *platform_default_s(char const *name)
754 {
755     return NULL;
756 }
757
758 int platform_default_i(char const *name, int def)
759 {
760
761     /* Non-raw cut and paste of line-drawing chars works badly on the
762      * current Unix stub implementation of the Unicode functions.
763      * So I'm going to temporarily set the default to raw mode so
764      * that the failure mode isn't quite so drastically horrid.
765      * When Unicode comes in, this can all be put right. */
766     if (!strcmp(name, "RawCNP"))
767         return 1;
768     return def;
769 }
770
771 void platform_get_x11_auth(char *display, int *proto,
772                            unsigned char *data, int *datalen)
773 {
774     /* SGT: I have no idea whether Mac X servers need anything here. */
775 }
776
777 void update_specials_menu(void *frontend)
778 {
779     Session *s = frontend;
780     WindowPtr front;
781
782     front = mac_frontwindow();
783     if (front != NULL && mac_windowsession(front) == s)
784         mac_adjustmenus();
785 }
786
787 /*
788  * Local Variables:
789  * c-file-style: "simon"
790  * End:
791  */