Missed two int/unsigned usages in BSSourceView.m
[macgdbp.git] / Source / BSSourceView.m
1 /*
2 * MacGDBp
3 * Copyright (c) 2007 - 2011, Blue Static <http://www.bluestatic.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
10 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17 #import "BSSourceView.h"
18
19 @interface BSSourceView (Private)
20 - (void)setupViews;
21 - (void)errorHighlightingFile:(NSNotification*)notif;
22 - (void)setPlainTextStringFromFile:(NSString*)filePath;
23 @end
24
25 @implementation BSSourceView
26
27 @synthesize numberView, textView, scrollView, markedLine, delegate, file;
28
29 /**
30 * Initializes the source view with the path of a file
31 */
32 - (id)initWithFrame:(NSRect)frame
33 {
34 if (self = [super initWithFrame:frame])
35 {
36 [self setupViews];
37 [[NSNotificationCenter defaultCenter]
38 addObserver:self
39 selector:@selector(errorHighlightingFile:)
40 name:NSFileHandleReadToEndOfFileCompletionNotification
41 object:nil
42 ];
43 }
44 return self;
45 }
46
47 /**
48 * Dealloc
49 */
50 - (void)dealloc
51 {
52 [file release];
53
54 [numberView removeFromSuperview];
55 [scrollView removeFromSuperview];
56 [textView removeFromSuperview];
57
58 [super dealloc];
59 }
60
61 /**
62 * Sets the file name as well as the text of the source view
63 */
64 - (void)setFile:(NSString*)f
65 {
66 if (file != f)
67 {
68 [file release];
69 file = [f retain];
70 }
71
72 if (![[NSFileManager defaultManager] fileExistsAtPath:f])
73 {
74 [textView setString:@""];
75 return;
76 }
77
78 @try
79 {
80 // Attempt to use the PHP CLI to highlight the source file as HTML
81 NSPipe* outPipe = [NSPipe pipe];
82 NSPipe* errPipe = [NSPipe pipe];
83 NSTask* task = [[NSTask new] autorelease];
84
85 [task setLaunchPath:@"/usr/bin/php"]; // This is the path to the default Leopard PHP executable
86 [task setArguments:[NSArray arrayWithObjects:@"-s", f, nil]];
87 [task setStandardOutput:outPipe];
88 [task setStandardError:errPipe];
89 [task launch];
90
91 [[errPipe fileHandleForReading] readToEndOfFileInBackgroundAndNotify];
92
93 NSData* data = [[outPipe fileHandleForReading] readDataToEndOfFile];
94 NSAttributedString* source = [[NSAttributedString alloc] initWithHTML:data documentAttributes:NULL];
95 [[textView textStorage] setAttributedString:source];
96 [source release];
97 }
98 @catch (NSException* exception)
99 {
100 // If the PHP executable is not available then the NSTask will throw an exception
101 [self setPlainTextStringFromFile:f];
102 }
103 }
104
105 /**
106 * Sets the contents of the SourceView via a string rather than loading from a path
107 */
108 - (void)setString:(NSString*)source asFile:(NSString*)path
109 {
110 // create the temp file
111 NSError* error = nil;
112 NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"MacGDBpHighlighter"];
113 [source writeToFile:tmpPath atomically:NO encoding:NSUTF8StringEncoding error:&error];
114 if (error)
115 {
116 [textView setString:source];
117 return;
118 }
119
120 // highlight the temporary file
121 [self setFile:tmpPath];
122
123 // delete the temp file
124 [[NSFileManager defaultManager] removeItemAtPath:tmpPath error:NULL];
125
126 // plop in our fake path so nobody knows the difference
127 if (path != file)
128 {
129 [file release];
130 file = [path copy];
131 }
132 }
133
134 /**
135 * If an error occurs in reading the highlighted PHP source, this will merely set the string
136 */
137 - (void)errorHighlightingFile:(NSNotification*)notif
138 {
139 NSData* data = [[notif userInfo] objectForKey:NSFileHandleNotificationDataItem];
140 if ([data length] > 0) // there's something on stderr, so the PHP CLI failed
141 [self setPlainTextStringFromFile:file];
142 }
143
144 /**
145 * Flip the coordinates
146 */
147 - (BOOL)isFlipped
148 {
149 return YES;
150 }
151
152 /**
153 * Tells the text view to scroll to a certain line
154 */
155 - (void)scrollToLine:(NSUInteger)line
156 {
157 if ([[textView textStorage] length] == 0)
158 return;
159
160 // go through the document until we find the NSRange for the line we want
161 NSUInteger rangeIndex = 0;
162 for (NSUInteger i = 0; i < line; i++)
163 {
164 rangeIndex = NSMaxRange([[textView string] lineRangeForRange:NSMakeRange(rangeIndex, 0)]);
165 }
166
167 // now get the true start/end markers for it
168 NSUInteger lineStart, lineEnd;
169 [[textView string] getLineStart:&lineStart end:NULL contentsEnd:&lineEnd forRange:NSMakeRange(rangeIndex - 1, 0)];
170 [textView scrollRangeToVisible:[[textView string] lineRangeForRange:NSMakeRange(lineStart, lineEnd - lineStart)]];
171 }
172
173 /**
174 * Setup all the subviews for the source metaview
175 */
176 - (void)setupViews
177 {
178 NSUInteger gutterWidth = 30;
179
180 // setup the line number view
181 NSRect numberFrame = [self bounds];
182 numberFrame.origin = NSMakePoint(0.0, 0.0);
183 numberFrame.size.width = gutterWidth;
184 numberView = [[BSLineNumberView alloc] initWithFrame:numberFrame];
185 [numberView setAutoresizingMask:NSViewHeightSizable];
186 [numberView setSourceView:self];
187 [self addSubview:numberView];
188
189 // create the scroll view
190 NSRect scrollFrame = [self bounds];
191 scrollFrame.origin.x = gutterWidth;
192 scrollFrame.size.width = scrollFrame.size.width - gutterWidth;
193 scrollView = [[NSScrollView alloc] initWithFrame:scrollFrame];
194 [scrollView setHasHorizontalScroller:YES];
195 [scrollView setHasVerticalScroller:YES];
196 [scrollView setAutohidesScrollers:YES];
197 [scrollView setBorderType:NSBezelBorder];
198 [scrollView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
199 [[scrollView contentView] setAutoresizesSubviews:YES];
200 [self addSubview:scrollView];
201
202 // add the text view to the scroll view
203 NSRect textFrame;
204 textFrame.origin = NSMakePoint(0.0, 0.0);
205 textFrame.size = [scrollView contentSize];
206 textView = [[BSSourceViewTextView alloc] initWithFrame:textFrame];
207 [textView setSourceView:self];
208 [textView setEditable:NO];
209 [textView setFont:[NSFont fontWithName:@"Monaco" size:10.0]];
210 [textView setHorizontallyResizable:YES];
211 [textView setVerticallyResizable:YES];
212 [textView setMinSize:textFrame.size];
213 [textView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
214 [[textView textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
215 [[textView textContainer] setWidthTracksTextView:NO];
216 [[textView textContainer] setHeightTracksTextView:NO];
217 [textView setAutoresizingMask:NSViewNotSizable];
218 [scrollView setDocumentView:textView];
219
220 NSArray* types = [NSArray arrayWithObject:NSFilenamesPboardType];
221 [self registerForDraggedTypes:types];
222 }
223
224 /**
225 * Gets the plain-text representation of the file at |filePath| and sets the
226 * contents in the source view.
227 */
228 - (void)setPlainTextStringFromFile:(NSString*)filePath
229 {
230 NSError* error;
231 NSString* contents = [NSString stringWithContentsOfFile:filePath
232 encoding:NSUTF8StringEncoding
233 error:&error];
234 if (error) {
235 NSLog(@"Error reading file at %@: %@", filePath, error);
236 return;
237 }
238 [textView setString:contents];
239 }
240
241 /**
242 * Validates an initiated drag operation.
243 */
244 - (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
245 {
246 if ([delegate respondsToSelector:@selector(sourceView:acceptsDropOfFile:)])
247 return NSDragOperationCopy;
248 return NSDragOperationNone;
249 }
250
251 /**
252 * Performs a dragging operation of files to set the contents of the file.
253 */
254 - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
255 {
256 NSPasteboard* pboard = [sender draggingPasteboard];
257 if ([[pboard types] containsObject:NSFilenamesPboardType]) {
258 NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
259 if ([files count]) {
260 NSString* filename = [files objectAtIndex:0];
261 if ([delegate respondsToSelector:@selector(sourceView:acceptsDropOfFile:)] &&
262 [delegate sourceView:self acceptsDropOfFile:filename]) {
263 [self setFile:filename];
264 return YES;
265 }
266 }
267 }
268 return NO;
269 }
270
271 @end