Fix placement of auxiliary IM window for Core Text
[MacVim.git] / src / MacVim / MMPlugInManager.m
blob9707d364e4c5cef46bbb147f5bf6d0e3803ca05a
1 /* vi:set ts=8 sts=4 sw=4 ft=objc:
2  *
3  * VIM - Vi IMproved            by Bram Moolenaar
4  *                              MacVim GUI port by Bjorn Winckler
5  *
6  * Do ":help uganda"  in Vim to read copying and usage conditions.
7  * Do ":help credits" in Vim to see a list of people who contributed.
8  * See README.txt for an overview of the Vim source code.
9  */
12  * MMPlugInManager
13  *
14  * This class is responsible for finding MacVim plugins at startup, loading
15  * them, and keeping track of them.
16  *
17  * Author: Matt Tolton
18  */
20 #import "MacVim.h"
22 #ifdef MM_ENABLE_PLUGINS
24 #import "MMPlugInManager.h"
25 #import "PlugInInterface.h"
26 #import "PlugInImpl.h"
28 @implementation MMPlugInManager
30 static NSString *ext = @"mmplugin";
32 static NSString *appSupportSubpath = @"Application Support/MacVim/PlugIns";
34 static MMPlugInManager *plugInManager = nil;
36 + (MMPlugInManager*)sharedManager
38     if (!plugInManager)
39         plugInManager = [[MMPlugInManager alloc] init];
41     return plugInManager;
44 - (id)init
46     if ((self = [super init]) == nil) return nil;
47     plugInClasses = [[NSMutableArray alloc] init];
48     return self;
51 - (void)dealloc
53     ASLogDebug(@"");
55     [plugInClasses release]; plugInClasses = nil;
56     [super dealloc];
59 - (NSArray *)plugInClasses;
61     return plugInClasses;
64 - (NSMutableArray *)allBundles
66     NSArray *librarySearchPaths;
67     NSEnumerator *searchPathEnum;
68     NSString *currPath;
69     NSMutableArray *bundleSearchPaths = [NSMutableArray array];
70     NSMutableArray *allBundles = [NSMutableArray array];
72     librarySearchPaths = NSSearchPathForDirectoriesInDomains(
73         NSLibraryDirectory, NSAllDomainsMask - NSSystemDomainMask, YES);
75     searchPathEnum = [librarySearchPaths objectEnumerator];
76     while(currPath = [searchPathEnum nextObject]) {
77         [bundleSearchPaths addObject:
78             [currPath stringByAppendingPathComponent:appSupportSubpath]];
79     }
81     [bundleSearchPaths addObject:
82         [[NSBundle mainBundle] builtInPlugInsPath]];
84     searchPathEnum = [bundleSearchPaths objectEnumerator];
85     while(currPath = [searchPathEnum nextObject]) {
86         NSDirectoryEnumerator *bundleEnum;
87         NSString *currBundlePath;
88         bundleEnum = [[NSFileManager defaultManager]
89             enumeratorAtPath:currPath];
90         if(bundleEnum) {
91             while(currBundlePath = [bundleEnum nextObject]) {
92                 if([[currBundlePath pathExtension] isEqualToString:ext]) {
93                  [allBundles addObject:[currPath
94                            stringByAppendingPathComponent:currBundlePath]];
95                 }
96             }
97         }
98     }
100     return allBundles;
103 - (BOOL)plugInClassIsValid:(Class)class
105     return [class conformsToProtocol:@protocol(PlugInProtocol)];
108 - (void)loadAllPlugIns
110     NSMutableArray *bundlePaths;
111     NSEnumerator *pathEnum;
112     NSString *currPath;
113     NSBundle *currBundle;
114     Class currPrincipalClass;
116     bundlePaths = [NSMutableArray array];
118     [bundlePaths addObjectsFromArray:[self allBundles]];
120     pathEnum = [bundlePaths objectEnumerator];
121     while(currPath = [pathEnum nextObject]) {
122         currBundle = [NSBundle bundleWithPath:currPath];
123         if(currBundle) {
124             currPrincipalClass = [currBundle principalClass];
125             if(currPrincipalClass && [self plugInClassIsValid:currPrincipalClass]) {
126                 if ([currPrincipalClass initializePlugIn:
127                     [MMPlugInAppMediator sharedAppMediator]]) {
128                     ASLogInfo(@"Plug-in initialized: %@", currPath);
129                     [plugInClasses addObject:currPrincipalClass];
130                 } else {
131                     ASLogErr(@"Plug-in failed to initialize: %@", currPath);
132                 }
133             } else {
134                 ASLogErr(@"Plug-in did not conform to protocol: %@", currPath);
135             }
136         }
137     }
140 - (void)unloadAllPlugIns
142     int i, count = [plugInClasses count];
143     for (i = 0; i < count; i++)
144         [[plugInClasses objectAtIndex:i] terminatePlugIn];
146     [plugInClasses removeAllObjects];
149 @end
151 #endif