added missing files
[TestXSLT.git] / XMLTextView.m
1 //
2 //  XMLTextView.m
3 //  TestXSLT
4 //
5 //  Created by Marc Liyanage on Fri Aug 02 2002.
6 //  Copyright (c) 2002 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "XMLTextView.h"
10
11
12 @implementation XMLTextView
13
14
15
16 -(void)awakeFromNib {
17
18         [self setRichText:NO];
19         resultstack = NULL;
20
21         
22         // register our two input text views to receive file drags
23         //
24  //     [xmlView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
25  //     [xsltView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
26         
27         NSFont *computerFont = [NSFont fontWithName:@"Courier" size:12.0];
28         [self setFont:computerFont];
29         
30         [self setAllowsUndo:YES];
31         
32 }
33
34
35 - (void)dealloc {
36         
37         if (resultstack)
38                 free(resultstack);
39         [errorString release];
40 }
41
42 -(void)selectLineByNumber:(int)line {
43
44         NSString *data = [self string];
45         unsigned int i, startIndex, lineEndIndex;
46         NSRange aRange;
47
48         if (line == 0) {
49                 return;
50         }
51
52
53         aRange.location = 0;
54         aRange.length = 0;
55
56         for (i = 1; i <= line; i++) {
57
58                 [data getLineStart:&startIndex end:&lineEndIndex contentsEnd:nil forRange:aRange];
59                 aRange.location = lineEndIndex;
60
61         }
62
63         aRange.location = startIndex;
64         aRange.length = lineEndIndex - startIndex;
65
66         [self setSelectedRange:aRange];
67         [self scrollRangeToVisible:aRange];
68
69         
70 }
71
72
73
74
75
76 - (void)keyDown:(NSEvent *)event {
77
78         NSRange selectedRange;
79         
80         if ([[event characters] isEqual:@"\033"]) {
81
82                 if ([event modifierFlags] || [event isARepeat]) {
83                         return;
84                 }
85                 [self complete:nil];
86                 return;
87
88         } else if ([[event characters] isEqual:@"/"]) {
89
90                 selectedRange = [self selectedRange];
91                 if (selectedRange.location < 2 || selectedRange.length > 0) {
92                         [super keyDown:event];
93                         return;
94                 }
95
96                 if ([[[self string] substringWithRange:NSMakeRange(selectedRange.location - 1, 1)] isEqual:@"<"]) {
97                         if([self completeAfterSlash]) {
98                                 return;
99                         }
100                 }
101         }
102
103         
104         /*
105         if ([event modifierFlags] & NSFunctionKeyMask) {
106                 [self didChangeText];
107         }
108         */
109         
110         //NSFunctionKeyMask
111         
112         
113         [super keyDown:event];
114
115 }
116
117
118
119 - (BOOL)completeAfterSlash {
120
121         int location = [self selectedRange].location - 1;
122         
123         [self calculateTagStackAtLocation:location];
124         
125         if (stackresult) {
126                 return NO;
127         }
128
129         NSTextStorage *storage = [self textStorage];
130         [storage beginEditing];
131         [storage deleteCharactersInRange:NSMakeRange(location, 1)];
132         [storage endEditing];
133
134         [self setSelectedRange:NSMakeRange(location, 0)];
135
136         [self complete:nil];
137
138         
139         return YES;
140 }
141
142
143
144 - (void)flashRange:(NSRange)range {
145
146         NSRect tagNameRect;
147
148         tagNameRect = [self firstRectForCharacterRange:range];
149
150         tagNameRect.origin = [[self window] convertScreenToBase:tagNameRect.origin];
151
152         tagNameRect = [self convertRect:tagNameRect fromView:[[self window] contentView]];
153
154
155         [self lockFocus];
156         [[[NSColor selectedControlColor] colorWithAlphaComponent:0.75] set];
157 /*
158         NSFrameRectWithWidth(tagNameRect, 2);
159  */
160         [NSBezierPath fillRect:tagNameRect];
161         [self unlockFocus];
162         [[self window] flushWindow];
163
164         usleep(100000);
165
166         [self setNeedsDisplay:YES];
167
168         
169 }
170
171 -(NSString *)calculateTagStack {
172
173         return [self calculateTagStackAtLocation:[self selectedRange].location];
174         
175 }
176
177 -(BOOL)checkWellFormed {
178
179         int result;
180         NSData *data = [XMLUtils getDataWithEncodingFromString:[self string]];
181
182         parser = XML_ParserCreate(NULL);
183
184         if (!parser) {
185                 NSLog(@"Unable to allocate expat parser in XMLTextView:checkWellFormed!");
186                 return NO;
187         }
188
189         result = XML_Parse(parser, [data bytes], [data length], 1);
190
191         if (!result) {
192                 [self setError:[NSString stringWithFormat:@"%s, line %d, column %d", XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser), XML_GetCurrentColumnNumber(parser)] atLine:XML_GetCurrentLineNumber(parser) atColumn:XML_GetCurrentColumnNumber(parser)];
193         } else if (error) {
194                 [self clearError];
195         }
196         
197         XML_ParserFree(parser);
198         
199         return result > 0;
200 }
201
202
203
204 -(void)clearError {
205         
206         errorLine = errorColumn = 0;
207         error = NO;
208         [errorString release];
209         errorString = @"";
210         
211 }
212
213 -(BOOL)hasError {
214         
215         return error;
216         
217 }
218 -(void)setError:(NSString *)errstring atLine:(int)line atColumn:(int)column {
219         
220         errorLine = line;
221         errorColumn = column;
222         error = YES;
223         [errstring retain];
224         [errorString release];
225         errorString = errstring;
226         
227 }
228
229
230
231
232
233
234
235 -(NSString *)calculateTagStackAtLocation:(int)location {
236
237         char *buffer;
238         int i;
239         NSRange selectedRange;
240         NSMutableString *mystack;
241         
242         buffer = [[self string] lossyCString];
243         selectedRange = [self selectedRange];
244         
245         if (resultstack)
246                 free(resultstack);
247
248         stackresult = 0;
249         resultstack = findCompletion(buffer, strlen(buffer), location, &stackresult, tagpositions);
250
251         mystack = [NSMutableString stringWithCapacity:1000];
252         
253         for (i = 0; resultstack && *(resultstack[i]); i++) {
254                 if (*(resultstack[i+1])) {
255                         [mystack appendFormat:@"%s/", resultstack[i]];
256                 } else {
257                         if (stackresult) {
258                                 [mystack appendFormat:@"%s", resultstack[i]];
259                         } else {
260                                 [mystack appendFormat:@"<%s>", resultstack[i]];
261                         }
262                         
263                         
264                 }
265
266         }
267
268
269         switch (stackresult) {
270         
271                 case 1:
272                         [mystack appendString:@" (In tag)"];
273                         break;
274
275                 case 3:
276                         [mystack appendString:@" (In comment section)"];
277                         break;
278                 case 5:
279                         [mystack appendString:@" (In CDATA section)"];
280                         break;
281                         
282                 case 8:
283                         [mystack appendString:@" (No open tags)"];
284                         break;
285                         
286                 case 16:
287                         [mystack appendString:@" (Tags are balanced)"];
288                         break;
289         }
290         
291         
292         return mystack;
293         
294 }
295
296 - (void)complete:(id)sender {
297
298         NSRange selectedRange, tagNameRange;
299         NSString *tagName = nil;
300         int location, i;
301
302 //      data = [self string];
303
304         selectedRange = [self selectedRange];
305         location = selectedRange.location;
306
307         /* May not have a selection, and insertion point must be preceded by at
308                 * least one tag, which means at least 3 characters must be to its left
309                 */
310         if (selectedRange.length > 0 || location < 3 || stackresult) {
311                 NSBeep();
312                 return;
313         }
314
315
316         for (i = 0; resultstack && *(resultstack[i]); i++) {
317                 if (!*(resultstack[i+1])) {
318                         tagName = [NSString stringWithCString:resultstack[i]];
319                         tagNameRange = NSMakeRange(tagpositions[i*2], tagpositions[i*2+1]- tagpositions[i*2]);
320                 }
321         }
322         
323
324         [self insertText:[NSString stringWithFormat:@"</%@>", tagName]];
325         [self setSelectedRange:selectedRange];
326
327         [self flashRange:tagNameRange];
328         [self calculateTagStack];
329         
330 }
331
332
333
334
335
336 @end