Changeset 88 for trunk/ICeCoffEE/ICeCoffEE/ICeCoffEEActionMenu.c
- Timestamp:
- 02/06/03 20:11:46 (21 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/ICeCoffEE/ICeCoffEE/ICeCoffEEActionMenu.c
r82 r88 10 10 #include "ICeCoffEEActionMenu.h" 11 11 #include "ICeCoffEEConfig.h" 12 #include "ICeCoffEEShared.h" 12 13 #include "ICeCoffEEBookmarks.h" 13 14 … … 32 33 CFURLRef defaultAppURL; // URL of default app, set to NULL after added to menu 33 34 CFMutableSetRef appPaths; 34 CFMutableDictionaryRef appNames; // keys: app display names (CFString), values: MenuItemIndex of matching item without path appended, or kICAppMenuItemHasPath if already appended (at least 2 items with this name exist) 35 CFMutableDictionaryRef appItemTitles; // keys: URLs; values: item titles (CFString) 36 CFMutableDictionaryRef appURLs; // keys: app display names (CFString), values: URL of item without path appended, or NULL if already appended (at least 2 items with this name exist) 35 37 MenuRef menu; 36 38 } icAppMenuContext; 37 39 38 static OSStatus ICCF_AddApp ToMenu(icAppMenuContext *ctx, CFURLRef appURL, MenuCommand menuCommand) {40 static OSStatus ICCF_AddAppItemTitle(icAppMenuContext *ctx, CFURLRef appURL) { 39 41 CFStringRef appName = NULL, appItemTitle = NULL; 40 42 CFBundleRef appBundle = NULL; 41 IconRef appIcon = NULL;42 FSRef appRef;43 SInt16 label;44 MenuItemIndex menuItemIndex;45 43 OSStatus err = noErr; 46 44 … … 48 46 // only one entry for each path 49 47 if (CFSetContainsValue(ctx->appPaths, appPath)) 50 return noErr;48 return dupFNErr; 51 49 CFSetAddValue(ctx->appPaths, appPath); 52 50 53 51 if ( (err = LSCopyDisplayNameForURL(appURL, &appName)) != noErr) 54 52 return err; 55 53 56 menuItemIndex = (long)CFDictionaryGetValue(ctx->appNames, appName); 57 if (menuItemIndex != 0) { 58 CFURLRef sameAppRef; 59 if (menuItemIndex != kICAppMenuItemHasPath && 60 GetMenuItemRefCon(ctx->menu, menuItemIndex, (void *)&sameAppRef) == noErr) { 61 CFStringRef sameAppItemTitle = NULL; 62 if ( (err = CopyMenuItemTextAsCFString(ctx->menu, menuItemIndex, &sameAppItemTitle)) != noErr) 63 return err; 64 CFStringRef appItemTitleWithVersion = ICCF_NameWithLocation(sameAppItemTitle, sameAppRef); 65 SetMenuItemTextWithCFString(ctx->menu, menuItemIndex, appItemTitleWithVersion); 66 SAFE_RELEASE(appItemTitleWithVersion); 67 CFDictionarySetValue(ctx->appNames, appName, (void *)(long)kICAppMenuItemHasPath); 68 } 54 // if we encounter multiple applications with the same display name, add locations to the menu item titles to disambiguate them 55 CFURLRef sameAppURL; 56 Boolean shouldAppendLocation; 57 if ( (shouldAppendLocation = CFDictionaryGetValueIfPresent(ctx->appURLs, appName, (const void **)&sameAppURL)) && (CFTypeRef)sameAppURL != kCFNull) { 58 // this app is the second encountered with the same name; go back and fix the menu item title of the first app 59 CFStringRef sameAppItemTitle = CFDictionaryGetValue(ctx->appItemTitles, sameAppURL); 60 CFStringRef appItemTitleWithVersion = ICCF_NameWithLocation(sameAppItemTitle, sameAppURL); 61 CFDictionarySetValue(ctx->appItemTitles, sameAppURL, appItemTitleWithVersion); 62 SAFE_RELEASE(appItemTitleWithVersion); 63 CFDictionarySetValue(ctx->appURLs, appName, kCFNull); 69 64 } 70 65 … … 84 79 } 85 80 86 if ( menuItemIndex != 0) {81 if (shouldAppendLocation) { 87 82 CFStringRef appItemTitleWithVersion = ICCF_NameWithLocation(appItemTitle, appURL); 88 83 CFRelease(appItemTitle); 89 84 appItemTitle = appItemTitleWithVersion; 85 } else { 86 CFDictionarySetValue(ctx->appURLs, appName, appURL); 90 87 } 91 88 … … 95 92 CFRelease(appItemTitle); 96 93 appItemTitle = appItemTitleWithDefault; 97 ctx->defaultAppURL = NULL; 98 } 99 94 ctx->defaultAppURL = NULL; // mark as added 95 } 96 97 CFDictionarySetValue(ctx->appItemTitles, appURL, appItemTitle); 98 CFRelease(appItemTitle); 99 100 return noErr; 101 } 102 103 static OSStatus ICCF_AddTitledAppToMenu(icAppMenuContext *ctx, CFURLRef appURL, MenuCommand menuCommand) { 104 CFStringRef appItemTitle = NULL; 105 IconRef appIcon = NULL; 106 FSRef appFSR; 107 SInt16 label; 108 MenuItemIndex menuItemIndex; 109 OSStatus err = noErr; 110 111 appItemTitle = CFDictionaryGetValue(ctx->appItemTitles, appURL); 112 if (appItemTitle == NULL) return fnfErr; 113 100 114 err = AppendMenuItemTextWithCFString(ctx->menu, appItemTitle, 0, 0, &menuItemIndex); 101 CFRelease(appItemTitle);102 115 if (err != noErr) return err; 103 116 104 if (!CFDictionaryContainsKey(ctx->appNames, appName)) { 105 CFDictionarySetValue(ctx->appNames, appName, (void *)(long)menuItemIndex); 106 CFRelease(appName); 107 } 108 109 if (!CFURLGetFSRef(appURL, &appRef)) return paramErr; 110 err = GetIconRefFromFileInfo(&appRef, 0, NULL, kFSCatInfoNone, NULL, kIconServicesNormalUsageFlag, &appIcon, &label); 117 if (!CFURLGetFSRef(appURL, &appFSR)) return paramErr; 118 err = GetIconRefFromFileInfo(&appFSR, 0, NULL, kFSCatInfoNone, NULL, kIconServicesNormalUsageFlag, &appIcon, &label); 111 119 if (err != noErr) return err; 112 120 … … 119 127 } 120 128 129 static OSStatus ICCF_AddAppToMenu(icAppMenuContext *ctx, CFURLRef appURL, MenuCommand menuCommand) { 130 OSStatus err = ICCF_AddAppItemTitle(ctx, appURL); 131 switch (err) { 132 case noErr: break; 133 case dupFNErr: return noErr; 134 default: return err; 135 } 136 return ICCF_AddTitledAppToMenu(ctx, appURL, menuCommand); 137 } 138 139 CFComparisonResult ICCF_CompareURLsByItemTitle(const void *url1, const void *url2, void *appItemTitles) { 140 CFStringRef appItemTitle1 = CFDictionaryGetValue((CFDictionaryRef)appItemTitles, (CFURLRef)url1); 141 CFStringRef appItemTitle2 = CFDictionaryGetValue((CFDictionaryRef)appItemTitles, (CFURLRef)url2); 142 return CFStringCompareWithOptions(appItemTitle1, appItemTitle2, 143 CFRangeMake(0, CFStringGetLength(appItemTitle1)), 144 kCFCompareCaseInsensitive | kCFCompareNumerically); 145 } 146 121 147 enum { 122 148 kICURLActionOpenWith = 'OpnW', … … 127 153 Handle h = NewHandle(0); 128 154 CFURLRef url = NULL; 129 CFArrayRef appURLs = NULL; // matching app URLs 155 CFArrayRef appURLsUnsorted = NULL; // matching app URLs 156 CFMutableArrayRef appURLs = NULL; // matching app URLs sorted by item title 130 157 CFArrayRef urlArray = NULL; // single-URL array 131 158 icAppMenuContext ctx = {NULL, NULL, NULL, NULL}; … … 140 167 NULL)) == NULL) THROW_ERR(paramErr); 141 168 169 if ( (err = _LSCopyApplicationURLsForItemURL(url, kLSRolesAll, &appURLsUnsorted)) != noErr) 170 THROW_ERR(err); 171 142 172 CFIndex appCount = 0; 143 if ( (err = _LSCopyApplicationURLsForItemURL(url, kLSRolesAll, &appURLs)) != noErr) 144 THROW_ERR(err); 145 146 if (appURLs == NULL || (appCount = CFArrayGetCount(appURLs)) == 0) 173 if (appURLsUnsorted == NULL || (appCount = CFArrayGetCount(appURLsUnsorted)) == 0) 147 174 THROW_ERR(kLSApplicationNotFoundErr); 148 175 176 if ( (appURLs = CFArrayCreateMutableCopy(NULL, appCount, appURLsUnsorted)) == NULL) 177 THROW_ERR(memFullErr); 178 149 179 if ( (ctx.appPaths = CFSetCreateMutable(NULL, appCount, &kCFCopyStringSetCallBacks)) == NULL) 150 180 THROW_ERR(memFullErr); 151 181 152 // values: index of single item with name; 0/NULL if no name; kICAppMenuItemHasPath if multiple items have name 153 if ( (ctx.appNames = CFDictionaryCreateMutable(NULL, appCount, &kCFCopyStringDictionaryKeyCallBacks, NULL)) == NULL) 154 THROW_ERR(memFullErr); 155 182 if ( (ctx.appItemTitles = CFDictionaryCreateMutable(NULL, appCount, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == NULL) 183 THROW_ERR(memFullErr); 184 185 if ( (ctx.appURLs = CFDictionaryCreateMutable(NULL, appCount, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)) == NULL) 186 THROW_ERR(memFullErr); 187 188 LSGetApplicationForURL(url, kLSRolesAll, NULL, &ctx.defaultAppURL); 189 190 CFIndex appIndex; 191 CFURLRef appURL; 192 for (appIndex = 0 ; appIndex < appCount ; appIndex++) { 193 appURL = CFArrayGetValueAtIndex(appURLs, appIndex); 194 err = ICCF_AddAppItemTitle(&ctx, appURL); 195 switch (err) { 196 case noErr: break; 197 case dupFNErr: 198 CFArrayRemoveValueAtIndex(appURLs, appIndex); 199 appIndex--; 200 appCount--; 201 break; 202 default: 203 THROW_ERR(err); 204 } 205 } 206 207 CFArraySortValues(appURLs, CFRangeMake(0, appCount), ICCF_CompareURLsByItemTitle, ctx.appItemTitles); 208 156 209 if ( (err = CreateNewMenu(0, kMenuAttrExcludesMarkColumn, &ctx.menu)) != noErr) 157 210 THROW_ERR(err); … … 164 217 THROW_ERR(memFullErr); 165 218 166 LSGetApplicationForURL(url, kLSRolesAll, NULL, &ctx.defaultAppURL);167 168 CFIndex appIndex;169 CFURLRef appURL;170 171 219 for (appIndex = 0 ; appIndex < appCount ; appIndex++) { 172 220 appURL = CFArrayGetValueAtIndex(appURLs, appIndex); 173 221 174 if ( (err = ICCF_Add AppToMenu(&ctx, appURL, kICURLActionOpenWith)) != noErr)222 if ( (err = ICCF_AddTitledAppToMenu(&ctx, appURL, kICURLActionOpenWith)) != noErr) 175 223 THROW_ERR(err); 176 224 } … … 223 271 SAFE_RELEASE(url); 224 272 SAFE_RELEASE(urlArray); 273 SAFE_RELEASE(appURLsUnsorted); 225 274 SAFE_RELEASE(appURLs); 226 SAFE_RELEASE(ctx.appNames);227 275 SAFE_RELEASE(ctx.appPaths); 276 SAFE_RELEASE(ctx.appItemTitles); 277 SAFE_RELEASE(ctx.appURLs); 228 278 229 279 return err;
Note:
See TracChangeset
for help on using the changeset viewer.