Saved breakpoints (or any breakpoint) that had a file that does not exist would crash...
[macgdbp.git] / Source / BSSourceView.m
1 /*
2 * MacGDBp
3 * Copyright (c) 2007 - 2008, 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 @end
23
24 @implementation BSSourceView
25
26 @synthesize numberView, textView, scrollView, markedLine, delegate, file;
27
28 /**
29 * Initializes the source view with the path of a file
30 */
31 - (id)initWithFrame:(NSRect)frame
32 {
33 if (self = [super initWithFrame:frame])
34 {
35 [self setupViews];
36 [[NSNotificationCenter defaultCenter] addObserver:self
37 selector:@selector(errorHighlightingFile:)
38 name:NSFileHandleReadToEndOfFileCompletionNotification
39 object:nil];
40 }
41 return self;
42 }
43
44 /**
45 * Dealloc
46 */
47 - (void)dealloc
48 {
49 [file release];
50
51 [numberView removeFromSuperview];
52 [scrollView removeFromSuperview];
53 [textView removeFromSuperview];
54
55 [super dealloc];
56 }
57
58 /**
59 * Sets the file name as well as the text of the source view
60 */
61 - (void)setFile:(NSString *)f
62 {
63 if (file != f)
64 {
65 [file release];
66 file = [f retain];
67 }
68
69 if (![[NSFileManager defaultManager] fileExistsAtPath:f])
70 {
71 [textView setString:@""];
72 return;
73 }
74
75 @try
76 {
77 // Attempt to use the PHP CLI to highlight the source file as HTML
78 NSPipe *outPipe = [NSPipe pipe];
79 NSPipe *errPipe = [NSPipe pipe];
80 NSTask *task = [[NSTask new] autorelease];
81
82 [task setLaunchPath:@"/usr/bin/php"]; // This is the path to the default Leopard PHP executable
83 [task setArguments:[NSArray arrayWithObjects:@"-s", f, nil]];
84 [task setStandardOutput:outPipe];
85 [task setStandardError:errPipe];
86 [task launch];
87
88 [[errPipe fileHandleForReading] readToEndOfFileInBackgroundAndNotify];
89
90 NSData *data = [[outPipe fileHandleForReading] readDataToEndOfFile];
91 NSAttributedString *source = [[NSAttributedString alloc] initWithHTML:data documentAttributes:NULL];
92 [[textView textStorage] setAttributedString:source];
93 [source release];
94 }
95 @catch (NSException *exception)
96 {
97 // If the PHP executable is not available then the NSTask will throw an exception
98 [textView setString:[NSString stringWithContentsOfFile:f]];
99 }
100 }
101
102 /**
103 * If an error occurs in reading the highlighted PHP source, this will merely set the string
104 */
105 - (void)errorHighlightingFile:(NSNotification *)notif
106 {
107 NSData *data = [[notif userInfo] objectForKey:NSFileHandleNotificationDataItem];
108 if ([data length] > 0) // there's something on stderr, so the PHP CLI failed
109 [textView setString:[NSString stringWithContentsOfFile:file]];
110 }
111
112 /**
113 * Flip the coordinates
114 */
115 - (BOOL)isFlipped
116 {
117 return YES;
118 }
119
120 /**
121 * Tells the text view to scroll to a certain line
122 */
123 - (void)scrollToLine:(int)line
124 {
125 if (![[NSFileManager defaultManager] fileExistsAtPath:file])
126 return;
127
128 // go through the document until we find the NSRange for the line we want
129 int rangeIndex = 0;
130 for (int i = 0; i < line; i++)
131 {
132 rangeIndex = NSMaxRange([[textView string] lineRangeForRange:NSMakeRange(rangeIndex, 0)]);
133 }
134
135 // now get the true start/end markers for it
136 unsigned lineStart, lineEnd;
137 [[textView string] getLineStart:&lineStart end:NULL contentsEnd:&lineEnd forRange:NSMakeRange(rangeIndex - 1, 0)];
138 [textView scrollRangeToVisible:[[textView string] lineRangeForRange:NSMakeRange(lineStart, lineEnd - lineStart)]];
139 }
140
141 /**
142 * Setup all the subviews for the source metaview
143 */
144 - (void)setupViews
145 {
146 int gutterWidth = 30;
147
148 // setup the line number view
149 NSRect numberFrame = [self bounds];
150 numberFrame.origin = NSMakePoint(0.0, 0.0);
151 numberFrame.size.width = gutterWidth;
152 numberView = [[BSLineNumberView alloc] initWithFrame:numberFrame];
153 [numberView setAutoresizingMask:NSViewHeightSizable];
154 [numberView setSourceView:self];
155 [self addSubview:numberView];
156
157 // create the scroll view
158 NSRect scrollFrame = [self bounds];
159 scrollFrame.origin.x = gutterWidth;
160 scrollFrame.size.width = scrollFrame.size.width - gutterWidth;
161 scrollView = [[NSScrollView alloc] initWithFrame:scrollFrame];
162 [scrollView setHasHorizontalScroller:YES];
163 [scrollView setHasVerticalScroller:YES];
164 [scrollView setAutohidesScrollers:YES];
165 [scrollView setBorderType:NSBezelBorder];
166 [scrollView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
167 [[scrollView contentView] setAutoresizesSubviews:YES];
168 [self addSubview:scrollView];
169
170 // add the text view to the scroll view
171 NSRect textFrame;
172 textFrame.origin = NSMakePoint(0.0, 0.0);
173 textFrame.size = [scrollView contentSize];
174 textView = [[BSSourceViewTextView alloc] initWithFrame:textFrame];
175 [textView setSourceView:self];
176 [textView setEditable:NO];
177 [textView setFont:[NSFont fontWithName:@"Monaco" size:10.0]];
178 [textView setHorizontallyResizable:YES];
179 [textView setVerticallyResizable:YES];
180 [textView setMinSize:textFrame.size];
181 [textView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
182 [[textView textContainer] setContainerSize:NSMakeSize(FLT_MAX, FLT_MAX)];
183 [[textView textContainer] setWidthTracksTextView:NO];
184 [[textView textContainer] setHeightTracksTextView:NO];
185 [textView setAutoresizingMask:NSViewNotSizable];
186 [scrollView setDocumentView:textView];
187 }
188
189 @end