Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 369 lines (300 sloc) 13.11 kb
4deff4d Initial check-in.
uli authored
1 //
2 // UKMultiSyntaxColoredTextDocument.m
3 // UKSyntaxColoredDocument
4 //
5 // Created by Uli Kusterer on Mon May 17 2004.
54174c9 @uliwitness Changed license, changed uses of NSMenuItem protocol to class.
authored
6 // Copyright (c) 2004 Uli Kusterer.
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would be
19 // appreciated but is not required.
20 //
21 // 2. Altered source versions must be plainly marked as such, and must not be
22 // misrepresented as being the original software.
23 //
24 // 3. This notice may not be removed or altered from any source
25 // distribution.
4deff4d Initial check-in.
uli authored
26 //
27
28 // -----------------------------------------------------------------------------
29 // Headers:
30 // -----------------------------------------------------------------------------
31
32 #import "UKMultiSyntaxColoredTextDocument.h"
33 #import "NSMenu+DeepSearch.h"
34
35
36 // -----------------------------------------------------------------------------
37 // Globals:
38 // -----------------------------------------------------------------------------
39
40 static NSMutableArray* sUKMSCTDSyntaxDefinitionFiles = nil; // Array of syntax definition file paths in NSStrings.
41 static NSMutableDictionary* sUKMSCTDSuffixToTagMappings = nil;
42
43 NSString* UKMultiSyntaxColoredTextDocumentSyntaxDefinitionChanged = @"UKMultiSyntaxColoredTextDocumentSyntaxDefinitionChanged";
44
45
46 @implementation UKMultiSyntaxColoredTextDocument
47
48 // -----------------------------------------------------------------------------
49 // syntaxDefinitionFiles:
50 // Return and, if needed, lazily allocate the array of available syntax
51 // definition files. This also updates the syntax definition menu by
52 // writing the file names without suffixes of the syntax definition files
53 // into the menu as menu items, whose tags are the indices into the array
54 // corresponding to them.
55 //
56 // REVISIONS:
57 // 2004-05-18 witness Documented.
58 // 2004-05-17 witness Created.
59 // -----------------------------------------------------------------------------
60
61 -(NSArray*) syntaxDefinitionFiles
62 {
63 if( !sUKMSCTDSyntaxDefinitionFiles )
64 {
65 sUKMSCTDSyntaxDefinitionFiles = [[NSMutableArray alloc] init];
66 sUKMSCTDSuffixToTagMappings = [[NSMutableDictionary alloc] init];
67
68 // Load from User's Application support:
69 NSString* fpath = [NSString stringWithFormat: @"%@/Library/Application Support/%@/Syntax Definitions/",
70 NSHomeDirectory(), UKSCTD_APPLICATION_NAME];
71 [self addSyntaxFilesFromFolderToArray: fpath];
72
73 // Load from global application support:
74 fpath = [NSString stringWithFormat: @"/Library/Application Support/%@/Syntax Definitions/",
75 UKSCTD_APPLICATION_NAME];
76 [self addSyntaxFilesFromFolderToArray: fpath];
77
78 // Load from folder in app bundle:
79 fpath = [[NSBundle mainBundle] pathForResource: @"Syntax Definitions" ofType: @""];
80 [self addSyntaxFilesFromFolderToArray: fpath];
81
82 // Now make the menu match:
83 [self rebuildSyntaxMenu];
84 }
85
86 return sUKMSCTDSyntaxDefinitionFiles;
87 }
88
89
90 // -----------------------------------------------------------------------------
91 // rebuildSyntaxMenu:
92 // Remove the old items from the syntax definition menu and add new menu
93 // items for them based on the syntax definition files array.
94 //
95 // REVISIONS:
96 // 2004-05-18 witness Extracted from syntaxDefinitionFiles.
97 // -----------------------------------------------------------------------------
98
99 -(void) rebuildSyntaxMenu
100 {
54174c9 @uliwitness Changed license, changed uses of NSMenuItem protocol to class.
authored
101 NSMenuItem* foundItem = nil;
4deff4d Initial check-in.
uli authored
102 NSMenu* syntaxMenu = nil;
103
104 // Find menu with menu items for syntax definitions:
105 if( !syntaxDefinitionMenu )
106 {
107 foundItem = [[NSApp mainMenu] findItemWithTarget:nil andAction: @selector(takeSyntaxDefinitionFilenameFromTagOf:)];
108 syntaxMenu = [foundItem menu];
109 }
110 else // If we have a menu in our outlet, use that instead:
111 {
112 syntaxMenu = syntaxDefinitionMenu;
113 foundItem = [syntaxDefinitionMenu itemAtIndex: 0]; // Assume we own the popup.
114 }
115
116 // Remove all old menu items from our menu:
54174c9 @uliwitness Changed license, changed uses of NSMenuItem protocol to class.
authored
117 NSMenuItem* currMItem = foundItem;
4deff4d Initial check-in.
uli authored
118 int currItemNum = [syntaxMenu indexOfItem: currMItem];
119
120 while( [currMItem action] == @selector(takeSyntaxDefinitionFilenameFromTagOf:) )
121 {
122 [syntaxMenu removeItem: currMItem];
123 if( currItemNum < [syntaxMenu numberOfItems] )
124 currMItem = [syntaxMenu itemAtIndex: currItemNum];
125 else
126 break;
127 }
128 /* Warning! This croaks if the code below doesn't find any syntax
129 definition files, because then all menu items have been removed
130 and it won't find the menu the next time! */
131
132 NSEnumerator* enny = [sUKMSCTDSyntaxDefinitionFiles objectEnumerator];
133 NSString* currPath = nil;
134 int x = 0;
135
136 while( (currPath = [enny nextObject]) )
137 {
138 NSString* dName = [[currPath lastPathComponent] stringByDeletingPathExtension];
139 NSMenuItem* currItem = [syntaxMenu addItemWithTitle: dName action: @selector(takeSyntaxDefinitionFilenameFromTagOf:)
140 keyEquivalent:@""];
141 [currItem setTag: x++]; // Remember array index of this one.
142
143 NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile: currPath];
144 NSEnumerator* suffixEnny = [[dict objectForKey: @"FileNameSuffixes"] objectEnumerator];
145 NSString* suffix = nil;
146 while(( suffix = [suffixEnny nextObject] ))
147 [sUKMSCTDSuffixToTagMappings setObject: [NSNumber numberWithInt: x -1] forKey: suffix];
148 }
149 }
150
151
152 // -----------------------------------------------------------------------------
153 // addSyntaxFilesFromFolder:
154 // Scan the specified folder for files and add all files (except the ones
155 // starting with a period) to our array of syntax definition file paths,
156 // as well as adding menu items for them.
157 //
158 // This appends to the array, so can be called several times in a row to
159 // scan several folders.
160 //
161 // REVISIONS:
162 // 2004-05-18 witness Documented.
163 // 2004-05-17 witness Created.
164 // -----------------------------------------------------------------------------
165
166 -(void) addSyntaxFilesFromFolderToArray: (NSString*)fpath
167 {
168 NSDirectoryEnumerator* enny = [[NSFileManager defaultManager] enumeratorAtPath: fpath];
169 NSString* currPath = nil;
170 NSString* currName = nil;
171
172 while( (currName = [enny nextObject]) )
173 {
174 if( [currName characterAtIndex: 0] == '.' )
175 continue;
176
177 currPath = [fpath stringByAppendingPathComponent: currName];
178 [sUKMSCTDSyntaxDefinitionFiles addObject: currPath];
179 }
180 }
181
182
183 // -----------------------------------------------------------------------------
184 // reloadSyntaxDefinitionFiles:
185 // Kill and recreate the list of syntax definition files.
186 //
187 // REVISIONS:
188 // 2004-05-18 witness Created.
189 // -----------------------------------------------------------------------------
190
191 -(void) reloadSyntaxDefinitionFiles
192 {
193 [sUKMSCTDSyntaxDefinitionFiles release];
194 sUKMSCTDSyntaxDefinitionFiles = nil;
195
196 [self syntaxDefinitionFiles];
197 }
198
199
200 // -----------------------------------------------------------------------------
201 // * CONSTRUCTOR:
202 // Lazily instantiate our array of syntax definition file paths and also
203 // init the syntax coloring scheme to use to the first item from that list.
204 //
205 // REVISIONS:
206 // 2004-05-18 witness Documented.
207 // 2004-05-17 witness Created.
208 // -----------------------------------------------------------------------------
209
210 -(id) init
211 {
212 self = [super init];
213 if( self )
214 {
215 syntaxDefinitionFilename = [[[self syntaxDefinitionFiles] objectAtIndex: 0] retain];
216 }
217 return self;
218 }
219
220
221 // -----------------------------------------------------------------------------
222 // * DESTRUCTOR:
223 //
224 // REVISIONS:
225 // 2004-05-18 witness Documented.
226 // 2004-05-17 witness Created.
227 // -----------------------------------------------------------------------------
228
229 -(void) dealloc
230 {
231 [syntaxDefinitionFilename release];
232 syntaxDefinitionFilename = nil;
233
234 [super dealloc];
235 }
236
237
238 // -----------------------------------------------------------------------------
239 // windowControllerDidLoadNib:
240 // If we're using a popup, reload the syntax definition list now that the
241 // NIB's been loaded and in the process populate the menu.
242 //
243 // REVISIONS:
244 // 2004-05-18 witness Created.
245 // -----------------------------------------------------------------------------
246
6dcf91b @uliwitness The document classes now let the view controller do the syntax coloring ...
authored
247 -(void) windowControllerDidLoadNib: (NSWindowController *)windowController
4deff4d Initial check-in.
uli authored
248 {
249 if( syntaxDefinitionMenu ) // Connected to a popup in our NIB?
250 [self rebuildSyntaxMenu];
251
fb656cd @uliwitness Shut up a deprecation warning.
authored
252 NSString* fileSuffix = [[self fileURL] pathExtension];
4deff4d Initial check-in.
uli authored
253 NSNumber* numObj = [sUKMSCTDSuffixToTagMappings objectForKey: fileSuffix];
254 if( numObj )
255 [self setSyntaxDefinitionFilename: [sUKMSCTDSyntaxDefinitionFiles objectAtIndex: [numObj intValue]]];
256
257 [super windowControllerDidLoadNib: windowController];
258 }
259
260
261 // -----------------------------------------------------------------------------
6dcf91b @uliwitness The document classes now let the view controller do the syntax coloring ...
authored
262 // syntaxDefinitionDictionaryForTextViewController:
4deff4d Initial check-in.
uli authored
263 // Return the syntax definition dictionary to use for colorizing. This
6dcf91b @uliwitness The document classes now let the view controller do the syntax coloring ...
authored
264 // implements a delegate method in UKSyntaxColoredTextViewController since
265 // that only looks for its files in the application bundle.
4deff4d Initial check-in.
uli authored
266 // -----------------------------------------------------------------------------
267
6dcf91b @uliwitness The document classes now let the view controller do the syntax coloring ...
authored
268 -(NSDictionary*) syntaxDefinitionDictionaryForTextViewController: (UKSyntaxColoredTextViewController*)sender
4deff4d Initial check-in.
uli authored
269 {
6dcf91b @uliwitness The document classes now let the view controller do the syntax coloring ...
authored
270 NSString* synDefName = [self syntaxDefinitionFilename]; // *not* syntaxDefinitionFilenameForTextViewController:.
4deff4d Initial check-in.
uli authored
271 return [NSDictionary dictionaryWithContentsOfFile: synDefName];
272 }
273
274
275 // -----------------------------------------------------------------------------
6dcf91b @uliwitness The document classes now let the view controller do the syntax coloring ...
authored
276 // syntaxDefinitionFilenameForTextViewController:
4deff4d Initial check-in.
uli authored
277 // Return the full pathname of the syntax definition file to use for
278 // syntax coloring.
279 // -----------------------------------------------------------------------------
280
281 -(NSString*) syntaxDefinitionFilename
282 {
283 return [[syntaxDefinitionFilename retain] autorelease];
284 }
285
286
287 // -----------------------------------------------------------------------------
288 // setSyntaxDefinitionFilename:
289 // Select a different syntax definition file name to be used for coloring.
290 // This also causes a recoloring of the text using the new coloring scheme.
291 //
292 // REVISIONS:
293 // 2004-05-18 witness Documented.
294 // 2004-05-17 witness Created.
295 // -----------------------------------------------------------------------------
296
297 -(void) setSyntaxDefinitionFilename:(NSString *)aSyntaxDefinitionFileName
298 {
299 [aSyntaxDefinitionFileName retain];
300 [syntaxDefinitionFilename release];
301 syntaxDefinitionFilename = aSyntaxDefinitionFileName;
302
303 [[NSNotificationCenter defaultCenter] postNotificationName: UKMultiSyntaxColoredTextDocumentSyntaxDefinitionChanged object: self];
304
305 [self recolorCompleteFile: self];
306 }
307
308
309 // -----------------------------------------------------------------------------
310 // takeSyntaxDefinitionFilenameFromTagOf:
311 // Menu action for our menu items that allow changing the syntax definition
312 // to use.
313 //
314 // REVISIONS:
315 // 2004-05-18 witness Created.
316 // -----------------------------------------------------------------------------
317
318 -(IBAction) takeSyntaxDefinitionFilenameFromTagOf: (id)sender
319 {
320 [self setSyntaxDefinitionFilename: [sUKMSCTDSyntaxDefinitionFiles objectAtIndex: [sender tag]]];
321 }
322
323
324 // -----------------------------------------------------------------------------
325 // validateMenuItem:
326 // Make sure the menu item for the syntax coloring scheme this file uses
327 // is selectable and checked.
328 //
329 // REVISIONS:
330 // 2004-05-18 witness Created.
331 // -----------------------------------------------------------------------------
332
333 -(BOOL) validateMenuItem: (NSMenuItem*)anItem
334 {
335 if( [anItem action] == @selector(takeSyntaxDefinitionFilenameFromTagOf:) )
336 {
337 [anItem setState: ([[sUKMSCTDSyntaxDefinitionFiles objectAtIndex: [anItem tag]] isEqualToString: [self syntaxDefinitionFilename]])];
338
339 return( [anItem tag] < [sUKMSCTDSyntaxDefinitionFiles count] );
340 }
341 else
342 return [super validateMenuItem: anItem];
343 }
344
345
346 // -----------------------------------------------------------------------------
347 // windowNibName:
348 // By default, UKMultiSyntaxColoredTextDocument uses a different NIB which
349 // includes a popup menu in the status bar. If you want the menu in the
350 // main menu bar instead, just subclass this and override this method to
351 // return [super windowNibName], which gets you the regular NIB from the
352 // superclass without the popup, and it'll cause the code in here to look
353 // for its menu in the menu bar because the syntaxDefinitionMenu outlet
354 // won't be set. Of course you can also return any other NIB you create
355 // here, though then it'll be your duty to keep it in sync with the
356 // "official" ones from me.
357 //
358 // REVISIONS:
359 // 2004-05-18 witness Created.
360 // -----------------------------------------------------------------------------
361
362 -(NSString*) windowNibName
363 {
364 return @"UKMultiSyntaxColoredTextDocument";
365 }
366
367
368 @end
Something went wrong with that request. Please try again.