The R Project SVN R-packages

Rev

Rev 5707 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
898 urbaneks 1
/*
2
 *  R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
3
 *  
4
 *  R.app Copyright notes:
1254 iacus 5
 *                     Copyright (C) 2004-5  The R Foundation
898 urbaneks 6
 *                     written by Stefano M. Iacus and Simon Urbanek
7
 *
8
 *                  
9
 *  R Copyright notes:
10
 *                     Copyright (C) 1995-1996   Robert Gentleman and Ross Ihaka
11
 *                     Copyright (C) 1998-2001   The R Development Core Team
12
 *                     Copyright (C) 2002-2004   The R Foundation
13
 *
14
 *  This program is free software; you can redistribute it and/or modify
15
 *  it under the terms of the GNU General Public License as published by
16
 *  the Free Software Foundation; either version 2 of the License, or
17
 *  (at your option) any later version.
18
 *
19
 *  This program is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  A copy of the GNU General Public License is available via WWW at
25
 *  http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
26
 *  writing to the Free Software Foundation, Inc., 59 Temple Place,
27
 *  Suite 330, Boston, MA  02111-1307  USA.
28
 *
29
 *  Created by Simon Urbanek on 1/11/05.
30
 */
31
 
32
#import "REditorTextStorage.h"
1397 urbaneks 33
#import "RGUI.h"
34
#import "PreferenceKeys.h"
898 urbaneks 35
 
36
@implementation REditorTextStorage
37
 
38
- (id) init
39
{
40
	self = [super init];
41
	if (self) {
1397 urbaneks 42
		cont = [[NSTextStorage alloc] init];
43
		highlightColorAttr = nil;
44
		currentHighlight = -1;
45
		pendingHilite = -1;
46
		insideReplaceEdited = NO;
1459 urbaneks 47
		[self updatePreferences];
1397 urbaneks 48
		[[Preferences sharedPreferences] addDependent:self];
898 urbaneks 49
	}
50
	return self;
51
}
52
 
53
- (void) dealloc
54
{
1397 urbaneks 55
	[[Preferences sharedPreferences] removeDependent:self];
56
	[[NSNotificationCenter defaultCenter] removeObserver:self];
898 urbaneks 57
	[cont release];
1253 urbaneks 58
	[super dealloc];
898 urbaneks 59
}
60
 
61
// mandatory primitive methods
62
 
63
- (NSString*) string
64
{
65
	return [cont string];
66
}
67
 
5707 urbaneks 68
- (NSDictionary *) attributesAtIndex:(NSUInteger)index effectiveRange:(NSRangePointer)aRange
898 urbaneks 69
{
1397 urbaneks 70
	[super ensureAttributesAreFixedInRange:NSMakeRange(index,1)];
898 urbaneks 71
	return [cont attributesAtIndex:index effectiveRange:aRange];
72
}
73
 
74
- (void) replaceCharactersInRange:(NSRange)aRange withString:(NSString *)aString
75
{
4644 urbaneks 76
	BOOL restoreInside;
1397 urbaneks 77
	int origLen = [self length];
1423 urbaneks 78
	if (currentHighlight>-1) [self resetHighlights];
898 urbaneks 79
	[cont replaceCharactersInRange:aRange withString:aString];
4644 urbaneks 80
	restoreInside = insideReplaceEdited;
1397 urbaneks 81
	insideReplaceEdited = YES;
82
	[super ensureAttributesAreFixedInRange:NSMakeRange(aRange.location,[aString length])];
83
	[self edited:NSTextStorageEditedCharacters range:aRange changeInLength:[self length] - origLen];
4644 urbaneks 84
	insideReplaceEdited = restoreInside;
1397 urbaneks 85
	if (pendingHilite>-1) {
86
		[self highlightCharacter:pendingHilite];
87
		pendingHilite = -1;
88
	}
898 urbaneks 89
}
90
 
4644 urbaneks 91
/* be careful! insideReplaceEdited should be treated as a stack, because edit request via add/setAttributes are valid and can span ever begin/endEdit, so the code beolw doe NOT work as it will reset insideReplaceEdited to NO even if it is not safe! This will lead to exceptions in notification */
92
- (void) beginEditing
93
{
94
	SLog(@"REditorTextStorage beginEditing");
95
	/* we cannot do this without storing the previous state! insideReplaceEdited = YES; */
96
	[super beginEditing];
97
}
98
 
99
- (void) endEditing
100
{
101
	SLog(@"REditorTextStorage endEditing");
102
	[super endEditing];
103
	/* insideReplaceEdited = NO; cannot do this! it could reset an outer lock */
104
	if (pendingHilite>-1) {
105
		[self highlightCharacter:pendingHilite];
106
		pendingHilite = -1;
107
	}
108
	if (pendingHilite == -2) {
109
		[self resetHighlights];
110
		pendingHilite = -1;
111
	}
112
}
113
 
898 urbaneks 114
- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)aRange
115
{
4644 urbaneks 116
	BOOL restoreInside = insideReplaceEdited;
117
	insideReplaceEdited = YES;
898 urbaneks 118
	[cont setAttributes:attributes range:aRange];
1397 urbaneks 119
	[super ensureAttributesAreFixedInRange:aRange];
898 urbaneks 120
	[self edited:NSTextStorageEditedAttributes range:aRange changeInLength:0];
4644 urbaneks 121
	insideReplaceEdited = restoreInside;
898 urbaneks 122
}
123
 
1397 urbaneks 124
- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)aRange
125
{
4644 urbaneks 126
	BOOL restoreInside = insideReplaceEdited;
5070 urbaneks 127
	// SLog(@"REditorTextStorage addAttribute: %@ (inside=%d)", name, insideReplaceEdited);
4644 urbaneks 128
	insideReplaceEdited = YES;
1397 urbaneks 129
	[cont addAttribute:name value:value range:aRange];
130
	[self ensureAttributesAreFixedInRange:aRange];
131
	[self edited:NSTextStorageEditedAttributes range:aRange changeInLength:0];
4644 urbaneks 132
	insideReplaceEdited = restoreInside;
1397 urbaneks 133
}
134
 
898 urbaneks 135
// end of primitive methods
136
 
1397 urbaneks 137
- (BOOL)fixesAttributesLazily
138
{
139
	return YES;
140
}
898 urbaneks 141
 
1397 urbaneks 142
- (NSLayoutManager*) layoutManager
143
{
144
	NSArray *lms = [self layoutManagers];
145
	if (lms) {
146
		int lmsc = [lms count];
5707 urbaneks 147
		if (lmsc > 0) {
148
			if (lmsc > 1)
149
                NSLog(@"REditorTextStorage(%@).layoutManager: more than one LM exists, returning the first one",self);
1397 urbaneks 150
			return [lms objectAtIndex:0];
151
		}
152
	}
153
	return nil;
154
}
898 urbaneks 155
 
1397 urbaneks 156
-(void)resetHighlights
157
{
4644 urbaneks 158
	SLog(@"REditorTextStorage resetHighlights (inside=%d)", insideReplaceEdited);
159
	if (insideReplaceEdited) {
160
		pendingHilite=-2;
161
		return;
162
	}
1397 urbaneks 163
	if (currentHighlight>-1) {
164
		if (currentHighlight<[cont length]) {
165
			NSLayoutManager *lm = [self layoutManager];
166
			if (lm) {
167
				NSRange fr = NSMakeRange(currentHighlight,1);
168
				NSDictionary *d = [lm temporaryAttributesAtCharacterIndex:currentHighlight effectiveRange:&fr];
169
				if (!d || [d objectForKey:NSBackgroundColorAttributeName]==nil) {
170
					fr = NSMakeRange(0,[self length]);
171
					SLog(@"resetHighlights: attribute at %d not found, clearing all %d characters - better safe than sorry", currentHighlight, fr.length);
172
				}
173
				[lm removeTemporaryAttribute:NSBackgroundColorAttributeName forCharacterRange:fr];
174
			}
175
		}
176
		currentHighlight=-1;
177
	}
178
}
179
 
180
-(void)highlightCharacter: (int) pos
181
{
4644 urbaneks 182
	SLog(@"REditorTextStorage highlightCharacter: %d (inside=%d)", pos, insideReplaceEdited);
1397 urbaneks 183
	if (insideReplaceEdited) {
184
		pendingHilite = pos;
185
		return;
186
	}
187
	[self resetHighlights];
188
	if (pos>=0 && pos<[self length]) {
189
		NSLayoutManager *lm = [self layoutManager];
190
		if (lm) {
191
			currentHighlight=pos;
192
			[lm setTemporaryAttributes:highlightColorAttr forCharacterRange:NSMakeRange(pos, 1)];
193
			[self performSelector:@selector(resetBackgroundColor:) withObject:nil afterDelay:braceHighlightInterval];
194
		} else SLog(@"highlightCharacter: attempt to set highlight %d beyond the text range 0:%d - I refuse!", pos, [self length]-1);
195
	}
196
}
197
 
198
-(void)resetBackgroundColor:(id)sender
199
{
200
	[self resetHighlights];
201
}
202
 
203
- (void) updatePreferences {
204
	NSColor *c = [Preferences unarchivedObjectForKey: @"braceHighlightColor" withDefault: nil];
205
	if (!c) c=[NSColor redColor];
206
	if (highlightColorAttr) [highlightColorAttr release];
207
	highlightColorAttr = [[NSDictionary alloc] initWithObjectsAndKeys:c, NSBackgroundColorAttributeName, nil];
208
	showMatchingBraces = [Preferences flagForKey:showBraceHighlightingKey withDefault: YES];
5721 urbaneks 209
	braceHighlightInterval = [Preferences floatForKey:highlightIntervalKey withDefault:0.3f];
1397 urbaneks 210
}
211
 
898 urbaneks 212
@end