X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/0c4b77992e89ec742c9a938395ddaf979b2747e0..4fa38586e9af919db6853d0436ea96478bdec477:/mac/mac.c diff --git a/mac/mac.c b/mac/mac.c index 21a2f010..0af40dfc 100644 --- a/mac/mac.c +++ b/mac/mac.c @@ -1,4 +1,4 @@ -/* $Id: mac.c,v 1.20 2003/01/08 22:46:12 ben Exp $ */ +/* $Id: mac.c,v 1.43 2003/02/02 15:59:00 ben Exp $ */ /* * Copyright (c) 1999 Ben Harris * All rights reserved. @@ -29,6 +29,8 @@ */ #include +#include +#include #include #include #include @@ -41,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -60,11 +63,14 @@ #include "ssh.h" #include "mac.h" +#if !TARGET_API_MAC_CARBON QDGlobals qd; +#endif Session *sesslist; static int cold = 1; +static int borednow = FALSE; struct mac_gestalts mac_gestalts; static void mac_startup(void); @@ -86,7 +92,6 @@ static void mac_adjustcursor(RgnHandle); static void mac_adjustmenus(void); static void mac_closewindow(WindowPtr); static void mac_zoomwindow(WindowPtr, short); -static void mac_shutdown(void); #pragma noreturn (cleanup_exit) struct mac_windows { @@ -108,6 +113,7 @@ static void mac_startup(void) { Handle menuBar; TECInfoHandle ti; +#if !TARGET_API_MAC_CARBON /* Init Memory Manager */ MaxApplZone(); /* Init QuickDraw */ @@ -122,6 +128,7 @@ static void mac_startup(void) { TEInit(); /* Init Dialog Manager */ InitDialogs(NULL); +#endif cold = 0; /* Get base system version (only used if there's no better selector) */ @@ -169,8 +176,13 @@ static void mac_startup(void) { mac_gestalts.uncvattr = (*ti)->tecUnicodeConverterFeatures; DisposeHandle((Handle)ti); } + /* Navigation Services? */ + if (NavServicesAvailable()) + mac_gestalts.navsvers = NavLibraryVersion(); + else + mac_gestalts.navsvers = 0; - mactcp_init(); + sk_init(); /* We've been tested with the Appearance Manager */ if (mac_gestalts.apprvers != 0) @@ -187,18 +199,20 @@ static void mac_startup(void) { windows.about = NULL; windows.licence = NULL; - default_protocol = DEFAULT_PROTOCOL; - default_port = DEFAULT_PORT; + default_protocol = be_default_protocol; + /* Find the appropriate default port. */ + { + int i; + default_port = 0; /* illegal */ + for (i = 0; backends[i].backend != NULL; i++) + if (backends[i].protocol == default_protocol) { + default_port = backends[i].backend->default_port; + break; + } + } flags = FLAG_INTERACTIVE; - /* - * Really grotty hack to ensure that anything that looks at the - * global "cfg" variable gets something vaguely sensible. - * Obviously, nothing should actually be using it, but that will - * take a while to arrange. - */ - do_defaults(NULL, &cfg); - +#if !TARGET_API_MAC_CARBON { short vol; long dirid; @@ -210,7 +224,17 @@ static void mac_startup(void) { LMSetCurDirStore(dirid); } } - init_ucs(); +#endif + + /* Install Apple Event handlers. */ + AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, + NewAEEventHandlerUPP(&mac_aevt_oapp), 0, FALSE); + AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, + NewAEEventHandlerUPP(&mac_aevt_odoc), 0, FALSE); + AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, + NewAEEventHandlerUPP(&mac_aevt_pdoc), 0, FALSE); + AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, + NewAEEventHandlerUPP(&mac_aevt_quit), 0, FALSE); } static void mac_eventloop(void) { @@ -225,7 +249,9 @@ static void mac_eventloop(void) { mac_adjustcursor(cursrgn); if (gotevent) mac_event(&event); - mactcp_poll(); + if (borednow) + cleanup_exit(0); + sk_poll(); mac_pollterm(); } DisposeRgn(cursrgn); @@ -234,7 +260,6 @@ static void mac_eventloop(void) { static void mac_event(EventRecord *event) { short part; WindowPtr window; - Point pt; switch (event->what) { case mouseDown: @@ -244,9 +269,11 @@ static void mac_event(EventRecord *event) { mac_adjustmenus(); mac_menucommand(MenuSelect(event->where)); break; +#if !TARGET_API_MAC_CARBON case inSysWindow: SystemClick(event, window); break; +#endif case inContent: if (window != FrontWindow()) /* XXX: check for movable modal dboxes? */ @@ -260,7 +287,16 @@ static void mac_event(EventRecord *event) { break; case inDrag: /* XXX: moveable modal check? */ +#if TARGET_API_MAC_CARBON + { + BitMap screenBits; + + GetQDGlobalsScreenBits(&screenBits); + DragWindow(window, event->where, &screenBits.bounds); + } +#else DragWindow(window, event->where, &qd.screenBits.bounds); +#endif break; case inGrow: mac_growwindow(window, event); @@ -282,24 +318,33 @@ static void mac_event(EventRecord *event) { case updateEvt: mac_updatewindow((WindowPtr)event->message); break; +#if !TARGET_API_MAC_CARBON case diskEvt: if (HiWord(event->message) != noErr) { + Point pt; + SetPt(&pt, 120, 120); DIBadMount(pt, event->message); } break; +#endif + case kHighLevelEvent: + AEProcessAppleEvent(event); /* errors? */ + break; } } static void mac_contentclick(WindowPtr window, EventRecord *event) { short item; + DialogRef dialog; switch (mac_windowtype(window)) { case wTerminal: mac_clickterm(window, event); break; case wAbout: - if (DialogSelect(event, &window, &item)) + dialog = GetDialogFromWindow(window); + if (DialogSelect(event, &dialog, &item)) switch (item) { case wiAboutLicence: mac_openlicence(); @@ -339,19 +384,25 @@ static void mac_activatewindow(WindowPtr window, EventRecord *event) { } static void mac_activateabout(WindowPtr window, EventRecord *event) { + DialogRef dialog; DialogItemType itemtype; Handle itemhandle; short item; Rect itemrect; int active; + dialog = GetDialogFromWindow(window); active = (event->modifiers & activeFlag) != 0; - GetDialogItem(window, wiAboutLicence, &itemtype, &itemhandle, &itemrect); + GetDialogItem(dialog, wiAboutLicence, &itemtype, &itemhandle, &itemrect); HiliteControl((ControlHandle)itemhandle, active ? 0 : 255); - DialogSelect(event, &window, &item); + DialogSelect(event, &dialog, &item); } -static void mac_updatewindow(WindowPtr window) { +static void mac_updatewindow(WindowPtr window) +{ +#if TARGET_API_MAC_CARBON + RgnHandle rgn; +#endif switch (mac_windowtype(window)) { case wTerminal: @@ -360,7 +411,14 @@ static void mac_updatewindow(WindowPtr window) { case wAbout: case wSettings: BeginUpdate(window); +#if TARGET_API_MAC_CARBON + rgn = NewRgn(); + GetPortVisibleRegion(GetWindowPort(window), rgn); + UpdateDialog(GetDialogFromWindow(window), rgn); + DisposeRgn(rgn); +#else UpdateDialog(window, window->visRgn); +#endif EndUpdate(window); break; case wLicence: @@ -374,17 +432,23 @@ static void mac_updatelicence(WindowPtr window) Handle h; int len; long fondsize; + Rect textrect; - SetPort(window); + SetPort((GrafPtr)GetWindowPort(window)); BeginUpdate(window); fondsize = GetScriptVariable(smRoman, smScriptSmallFondSize); TextFont(HiWord(fondsize)); TextSize(LoWord(fondsize)); h = Get1Resource('TEXT', wLicence); len = GetResourceSizeOnDisk(h); +#if TARGET_API_MAC_CARBON + GetPortBounds(GetWindowPort(window), &textrect); +#else + textrect = window->portRect; +#endif if (h != NULL) { HLock(h); - TETextBox(*h, len, &window->portRect, teFlushDefault); + TETextBox(*h, len, &textrect, teFlushDefault); HUnlock(h); } EndUpdate(window); @@ -400,7 +464,7 @@ static int mac_windowtype(WindowPtr window) { if (window == NULL) return wNone; - kind = ((WindowPeek)window)->windowKind; + kind = GetWindowKind(window); if (kind < 0) return wDA; if (GetWVariant(window) == zoomDocProc) @@ -439,14 +503,17 @@ static void mac_keypress(EventRecord *event) { static void mac_menucommand(long result) { short menu, item; - Str255 da; WindowPtr window; +#if !TARGET_API_MAC_CARBON + Str255 da; +#endif menu = HiWord(result); item = LoWord(result); window = FrontWindow(); /* Things which do the same whatever window we're in. */ switch (menu) { +#if !TARGET_API_MAC_CARBON case mApple: switch (item) { case iAbout: @@ -458,6 +525,7 @@ static void mac_menucommand(long result) { goto done; } break; +#endif case mFile: switch (item) { case iNew: @@ -469,6 +537,15 @@ static void mac_menucommand(long result) { case iClose: mac_closewindow(window); goto done; + case iSave: + mac_savesession(); + goto done; + case iSaveAs: + mac_savesessionas(); + goto done; + case iDuplicate: + mac_dupsession(); + goto done; case iQuit: cleanup_exit(0); goto done; @@ -495,11 +572,12 @@ static void mac_openabout(void) { if (windows.about) SelectWindow(windows.about); else { - windows.about = GetNewDialog(wAbout, NULL, (WindowPtr)-1); + windows.about = + GetDialogWindow(GetNewDialog(wAbout, NULL, (WindowPtr)-1)); vers = (VersRecHndl)Get1Resource('vers', 1); if (vers != NULL && *vers != NULL) { longvers = (*vers)->shortVersion + (*vers)->shortVersion[0] + 1; - GetDialogItem(windows.about, wiAboutVersion, + GetDialogItem(GetDialogFromWindow(windows.about), wiAboutVersion, &itemtype, &item, &box); assert(itemtype & kStaticTextDialogItem); SetDialogItemText(item, longvers); @@ -521,22 +599,21 @@ static void mac_openlicence(void) { static void mac_closewindow(WindowPtr window) { switch (mac_windowtype(window)) { +#if !TARGET_API_MAC_CARBON case wDA: CloseDeskAcc(((WindowPeek)window)->windowKind); break; +#endif case wTerminal: - /* FIXME: end session and stuff */ + mac_closeterm(window); break; case wAbout: windows.about = NULL; - CloseWindow(window); + DisposeDialog(GetDialogFromWindow(window)); break; case wLicence: windows.licence = NULL; - CloseWindow(window); - break; - default: - CloseWindow(window); + DisposeWindow(window); break; } } @@ -549,6 +626,11 @@ static void mac_zoomwindow(WindowPtr window, short part) { /* * Make the menus look right before the user gets to see them. */ +#if TARGET_API_MAC_CARBON +/* XXX Is this good enough? What about Carbon on OS 8.1? */ +#define EnableItem EnableMenuItem +#define DisableItem DisableMenuItem +#endif static void mac_adjustmenus(void) { WindowPtr window; MenuHandle menu; @@ -568,10 +650,20 @@ static void mac_adjustmenus(void) { EnableItem(menu, iQuit); switch (mac_windowtype(window)) { + case wSettings: + DisableItem(menu, iSave); /* XXX enable if modified */ + EnableItem(menu, iSaveAs); + EnableItem(menu, iDuplicate); + menu = GetMenuHandle(mEdit); + DisableItem(menu, 0); + break; case wTerminal: mac_adjusttermmenus(window); break; default: + DisableItem(menu, iSave); + DisableItem(menu, iSaveAs); + DisableItem(menu, iDuplicate); menu = GetMenuHandle(mEdit); DisableItem(menu, 0); break; @@ -586,6 +678,10 @@ static void mac_adjustcursor(RgnHandle cursrgn) { Point mouse; WindowPtr window, front; short part; +#if TARGET_API_MAC_CARBON + Cursor arrow; + RgnHandle visrgn; +#endif GetMouse(&mouse); LocalToGlobal(&mouse); @@ -593,23 +689,56 @@ static void mac_adjustcursor(RgnHandle cursrgn) { front = FrontWindow(); if (part != inContent || window == NULL || window != front) { /* Cursor isn't in the front window, so switch to arrow */ +#if TARGET_API_MAC_CARBON + GetQDGlobalsArrow(&arrow); + SetCursor(&arrow); +#else SetCursor(&qd.arrow); +#endif SetRectRgn(cursrgn, SHRT_MIN, SHRT_MIN, SHRT_MAX, SHRT_MAX); - if (front != NULL) + if (front != NULL) { +#if TARGET_API_MAC_CARBON + visrgn = NewRgn(); + GetPortVisibleRegion(GetWindowPort(front), visrgn); + DiffRgn(cursrgn, visrgn, cursrgn); + DisposeRgn(visrgn); +#else DiffRgn(cursrgn, front->visRgn, cursrgn); +#endif + } } else { switch (mac_windowtype(window)) { case wTerminal: mac_adjusttermcursor(window, mouse, cursrgn); break; default: +#if TARGET_API_MAC_CARBON + GetQDGlobalsArrow(&arrow); + SetCursor(&arrow); + GetPortVisibleRegion(GetWindowPort(window), cursrgn); +#else SetCursor(&qd.arrow); CopyRgn(window->visRgn, cursrgn); +#endif break; } } } +pascal OSErr mac_aevt_quit(const AppleEvent *req, AppleEvent *reply, + long refcon) +{ + DescType type; + Size size; + + if (AEGetAttributePtr(req, keyMissedKeywordAttr, typeWildCard, + &type, NULL, 0, &size) == noErr) + return errAEParamMissed; + + borednow = 1; + return noErr; +} + void cleanup_exit(int status) { @@ -617,7 +746,7 @@ void cleanup_exit(int status) if (mac_gestalts.encvvers != 0) TerminateUnicodeConverter(); #endif - mactcp_shutdown(); + sk_cleanup(); exit(status); } @@ -631,7 +760,7 @@ void fatalbox(char *fmt, ...) { va_end(ap); ParamText(stuff, NULL, NULL, NULL); StopAlert(128, NULL); - exit(1); + cleanup_exit(1); } void modalfatalbox(char *fmt, ...) { @@ -644,7 +773,7 @@ void modalfatalbox(char *fmt, ...) { va_end(ap); ParamText(stuff, NULL, NULL, NULL); StopAlert(128, NULL); - exit(1); + cleanup_exit(1); } /* This should only kill the current session, not the whole application. */ @@ -658,7 +787,7 @@ void connection_fatal(void *fontend, char *fmt, ...) { va_end(ap); ParamText(stuff, NULL, NULL, NULL); StopAlert(128, NULL); - exit(1); + cleanup_exit(1); } /* Null SSH agent client -- never finds an agent. */ @@ -694,6 +823,145 @@ void old_keyfile_warning(void) } +FontSpec platform_default_fontspec(char const *name) +{ + FontSpec ret; + long smfs; + + if (!strcmp(name, "Font")) { + smfs = GetScriptVariable(smSystemScript, smScriptMonoFondSize); + if (smfs == 0) + smfs = GetScriptVariable(smRoman, smScriptMonoFondSize); + if (smfs != 0) { + GetFontName(HiWord(smfs), ret.name); + if (ret.name[0] == 0) + memcpy(ret.name, "\pMonaco", 7); + ret.size = LoWord(smfs); + } else { + memcpy(ret.name, "\pMonaco", 7); + ret.size = 9; + } + ret.face = 0; + } else { + ret.name[0] = 0; + } + + return ret; +} + +Filename platform_default_filename(const char *name) +{ + Filename ret; + if (!strcmp(name, "LogFileName")) + FSMakeFSSpec(0, 0, "\pputty.log", &ret.fss); + else + memset(&ret, 0, sizeof(ret)); + return ret; +} + +char *platform_default_s(char const *name) +{ + return NULL; +} + +int platform_default_i(char const *name, int def) +{ + + /* Non-raw cut and paste of line-drawing chars works badly on the + * current Unix stub implementation of the Unicode functions. + * So I'm going to temporarily set the default to raw mode so + * that the failure mode isn't quite so drastically horrid. + * When Unicode comes in, this can all be put right. */ + if (!strcmp(name, "RawCNP")) + return 1; + return def; +} + +void platform_get_x11_auth(char *display, int *proto, + unsigned char *data, int *datalen) +{ + /* SGT: I have no idea whether Mac X servers need anything here. */ +} + +Filename filename_from_str(const char *str) +{ + Filename ret; + Str255 tmp; + + /* XXX This fails for filenames over 255 characters long. */ + c2pstrcpy(tmp, str); + FSMakeFSSpec(0, 0, tmp, &ret.fss); + return ret; +} + +/* + * Convert a filename to a string for display purposes. + * See pp 2-44--2-46 of IM:Files + * + * XXX static storage considered harmful + */ +const char *filename_to_str(const Filename *fn) +{ + CInfoPBRec pb; + Str255 dirname; + OSErr err; + static char *path = NULL; + char *newpath; + + if (path != NULL) sfree(path); + path = smalloc(fn->fss.name[0]); + p2cstrcpy(path, fn->fss.name); + pb.dirInfo.ioNamePtr = dirname; + pb.dirInfo.ioVRefNum = fn->fss.vRefNum; + pb.dirInfo.ioDrParID = fn->fss.parID; + pb.dirInfo.ioFDirIndex = -1; + do { + pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; + err = PBGetCatInfoSync(&pb); + + /* XXX Assume not A/UX */ + newpath = smalloc(strlen(path) + dirname[0] + 2); + p2cstrcpy(newpath, dirname); + strcat(newpath, ":"); + strcat(newpath, path); + sfree(path); + path = newpath; + } while (pb.dirInfo.ioDrDirID != fsRtDirID); + return path; +} + +int filename_equal(Filename f1, Filename f2) +{ + + return f1.fss.vRefNum == f2.fss.vRefNum && + f1.fss.parID == f2.fss.parID && + f1.fss.name[0] == f2.fss.name[0] && + memcmp(f1.fss.name + 1, f2.fss.name + 1, f1.fss.name[0]) == 0; +} + +int filename_is_null(Filename fn) +{ + + return fn.fss.vRefNum == 0 && fn.fss.parID == 0 && fn.fss.name[0] == 0; +} + +FILE *f_open(Filename fn, char const *mode) +{ + short savevol; + long savedir; + char tmp[256]; + FILE *ret; + + HGetVol(NULL, &savevol, &savedir); + if (HSetVol(NULL, fn.fss.vRefNum, fn.fss.parID) == noErr) { + p2cstrcpy(tmp, fn.fss.name); + ret = fopen(tmp, mode); + } else + ret = NULL; + HSetVol(NULL, savevol, savedir); + return ret; +} + /* * Local Variables: * c-file-style: "simon"