The R Project SVN R-packages

Rev

Rev 7916 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 7916 Rev 7929
1
/*
1
/*
2
 *  R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
2
 *  R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
3
 *  
3
 *  
4
 *  R.app Copyright notes:
4
 *  R.app Copyright notes:
5
 *                     Copyright (C) 2004-12  The R Foundation
5
 *                     Copyright (C) 2004-12  The R Foundation
6
 *                     written by Stefano M. Iacus and Simon Urbanek
6
 *                     written by Stefano M. Iacus and Simon Urbanek
7
 *
7
 *
8
 *                  
8
 *                  
9
 *  R Copyright notes:
9
 *  R Copyright notes:
10
 *                     Copyright (C) 1995-1996   Robert Gentleman and Ross Ihaka
10
 *                     Copyright (C) 1995-1996   Robert Gentleman and Ross Ihaka
11
 *                     Copyright (C) 1998-2001   The R Development Core Team
11
 *                     Copyright (C) 1998-2001   The R Development Core Team
12
 *                     Copyright (C) 2002-2004   The R Foundation
12
 *                     Copyright (C) 2002-2004   The R Foundation
13
 *
13
 *
14
 *  This program is free software; you can redistribute it and/or modify
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
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
16
 *  the Free Software Foundation; either version 2 of the License, or
17
 *  (at your option) any later version.
17
 *  (at your option) any later version.
18
 *
18
 *
19
 *  This program is distributed in the hope that it will be useful,
19
 *  This program is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
22
 *  GNU General Public License for more details.
23
 *
23
 *
24
 *  A copy of the GNU General Public License is available via WWW at
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
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,
26
 *  writing to the Free Software Foundation, Inc., 59 Temple Place,
27
 *  Suite 330, Boston, MA  02111-1307  USA.
27
 *  Suite 330, Boston, MA  02111-1307  USA.
28
 *
28
 *
29
 *  RScriptEditorTextStorage.m
29
 *  RScriptEditorTextStorage.m
30
 *
30
 *
31
 *  Created by Hans-J. Bibiko on 01/03/2012.
31
 *  Created by Hans-J. Bibiko on 01/03/2012.
32
 *
32
 *
33
 */
33
 */
34
 
34
 
35
#import "RScriptEditorTextStorage.h"
35
#import "RScriptEditorTextStorage.h"
36
#import "RScriptEditorTypesetter.h"
36
#import "RScriptEditorTypeSetter.h"
37
#import "RScriptEditorTextView.h"
37
#import "RScriptEditorTextView.h"
38
#import "FoldingSignTextAttachmentCell.h"
38
#import "FoldingSignTextAttachmentCell.h"
39
#import "RGUI.h"
39
#import "RGUI.h"
40
 
40
 
41
@implementation RScriptEditorTextStorage
41
@implementation RScriptEditorTextStorage
42
 
42
 
43
static NSTextAttachment *sharedAttachment = nil;
43
static NSTextAttachment *sharedAttachment = nil;
44
static SEL _getSel;
44
static SEL _getSel;
45
static SEL _setSel;
45
static SEL _setSel;
46
static SEL _strSel;
46
static SEL _strSel;
47
static SEL _replSel;
47
static SEL _replSel;
48
static SEL _editSel;
48
static SEL _editSel;
49
static SEL _getlSel;
49
static SEL _getlSel;
50
 
50
 
51
+ (void)initialize
51
+ (void)initialize
52
{
52
{
53
 
53
 
54
	if ([self class] == [RScriptEditorTextStorage class]) {
54
	if ([self class] == [RScriptEditorTextStorage class]) {
55
		FoldingSignTextAttachmentCell *cell = [[FoldingSignTextAttachmentCell alloc] initImageCell:nil];
55
		FoldingSignTextAttachmentCell *cell = [[FoldingSignTextAttachmentCell alloc] initImageCell:nil];
56
		sharedAttachment = [[NSTextAttachment alloc] init];
56
		sharedAttachment = [[NSTextAttachment alloc] init];
57
		[sharedAttachment setAttachmentCell:cell];
57
		[sharedAttachment setAttachmentCell:cell];
58
		[cell release];
58
		[cell release];
59
		_getSel  = @selector(attributesAtIndex:effectiveRange:);
59
		_getSel  = @selector(attributesAtIndex:effectiveRange:);
60
		_setSel  = @selector(setAttributes:range:);
60
		_setSel  = @selector(setAttributes:range:);
61
		_strSel  = @selector(string);
61
		_strSel  = @selector(string);
62
		_replSel = @selector(replaceCharactersInRange:withString:);
62
		_replSel = @selector(replaceCharactersInRange:withString:);
63
		_editSel = @selector(edited:range:changeInLength:);
63
		_editSel = @selector(edited:range:changeInLength:);
64
		_getlSel = @selector(attribute:atIndex:longestEffectiveRange:inRange:);
64
		_getlSel = @selector(attribute:atIndex:longestEffectiveRange:inRange:);
65
 
65
 
66
	}
66
	}
67
}
67
}
68
 
68
 
69
+ (NSTextAttachment *)attachment
69
+ (NSTextAttachment *)attachment
70
{
70
{
71
	return sharedAttachment;
71
	return sharedAttachment;
72
}
72
}
73
 
73
 
74
- (id)initWithDelegate:(id)theDelegate
74
- (id)initWithDelegate:(id)theDelegate
75
{
75
{
76
	self = [super init];
76
	self = [super init];
77
 
77
 
78
	if (self != nil) {
78
	if (self != nil) {
79
		_attributedString = [[NSTextStorage alloc] init];
79
		_attributedString = [[NSTextStorage alloc] init];
80
 
80
 
81
		selfDelegate = (RScriptEditorTextView*)theDelegate;
81
		selfDelegate = (RScriptEditorTextView*)theDelegate;
82
		[self setDelegate:theDelegate];
82
		[self setDelegate:theDelegate];
83
		foldedCounter = 0;
83
		foldedCounter = 0;
84
		currentMaxFoldedIndex = -1;
84
		currentMaxFoldedIndex = -1;
85
 
85
 
86
		for(NSInteger i = 0; i < R_MAX_FOLDED_ITEMS; i++) {
86
		for(NSInteger i = 0; i < R_MAX_FOLDED_ITEMS; i++) {
87
			foldedRanges[i][0] = -1;
87
			foldedRanges[i][0] = -1;
88
			foldedRanges[i][1] = 0;
88
			foldedRanges[i][1] = 0;
89
			foldedRanges[i][2] = 0;
89
			foldedRanges[i][2] = 0;
90
		}
90
		}
91
	}
91
	}
92
 
92
 
93
	return self;
93
	return self;
94
}
94
}
95
 
95
 
96
- (void)dealloc
96
- (void)dealloc
97
{
97
{
98
	[[NSNotificationCenter defaultCenter] removeObserver:self];
98
	[[NSNotificationCenter defaultCenter] removeObserver:self];
99
	[_attributedString release];
99
	[_attributedString release];
100
	if(sharedAttachment) [sharedAttachment release];
100
	if(sharedAttachment) [sharedAttachment release];
101
	[super dealloc];
101
	[super dealloc];
102
}
102
}
103
 
103
 
104
- (BOOL)hasFoldedItems
104
- (BOOL)hasFoldedItems
105
{
105
{
106
	return (foldedCounter == 0) ? NO : YES;
106
	return (foldedCounter == 0) ? NO : YES;
107
}
107
}
108
 
108
 
109
- (BOOL)inFoldedRangeForRange:(NSRange)range
109
- (BOOL)inFoldedRangeForRange:(NSRange)range
110
{
110
{
111
	if(!foldedCounter) return NO;
111
	if(!foldedCounter) return NO;
112
 
112
 
113
	NSInteger i = 0;
113
	NSInteger i = 0;
114
	NSInteger maxRange = NSMaxRange(range);
114
	NSInteger maxRange = NSMaxRange(range);
115
	NSInteger rangeLoc = range.location;
115
	NSInteger rangeLoc = range.location;
116
	for(i = 0; i < currentMaxFoldedIndex+1; i++) {
116
	for(i = 0; i < currentMaxFoldedIndex+1; i++) {
117
		if(rangeLoc > foldedRanges[i][0] && maxRange <= foldedRanges[i][2]) {
117
		if(rangeLoc > foldedRanges[i][0] && maxRange <= foldedRanges[i][2]) {
118
			return YES;
118
			return YES;
119
		}
119
		}
120
	}
120
	}
121
	return NO;
121
	return NO;
122
	
122
	
123
}
123
}
124
 
124
 
125
- (NSInteger)foldedAtIndex:(NSInteger)index
125
- (NSInteger)foldedAtIndex:(NSInteger)index
126
{
126
{
127
 
127
 
128
	if(!foldedCounter) return -1;
128
	if(!foldedCounter) return -1;
129
 
129
 
130
	NSInteger i = 0;
130
	NSInteger i = 0;
131
	for(i = 0; i < currentMaxFoldedIndex+1; i++) {
131
	for(i = 0; i < currentMaxFoldedIndex+1; i++) {
132
		if(foldedRanges[i][2] > index && foldedRanges[i][0] <= index) {
132
		if(foldedRanges[i][2] > index && foldedRanges[i][0] <= index) {
133
			return i;
133
			return i;
134
		}
134
		}
135
	}
135
	}
136
	return -1;
136
	return -1;
137
}
137
}
138
 
138
 
139
- (NSInteger)foldedForIndicatorAtIndex:(NSInteger)index
139
- (NSInteger)foldedForIndicatorAtIndex:(NSInteger)index
140
{
140
{
141
 
141
 
142
	if(!foldedCounter) return -1;
142
	if(!foldedCounter) return -1;
143
 
143
 
144
	if(index) {
144
	if(index) {
145
		// Folded ranges are stored from { to } but indicator will drawn inside of { and }
145
		// Folded ranges are stored from { to } but indicator will drawn inside of { and }
146
		NSInteger adjIndex = index + 1;
146
		NSInteger adjIndex = index + 1;
147
		for(NSInteger i = 0; i < currentMaxFoldedIndex+1; i++) {
147
		for(NSInteger i = 0; i < currentMaxFoldedIndex+1; i++) {
148
			if(foldedRanges[i][2] > adjIndex && foldedRanges[i][0] < index) {
148
			if(foldedRanges[i][2] > adjIndex && foldedRanges[i][0] < index) {
149
				return i;
149
				return i;
150
			}
150
			}
151
		}
151
		}
152
	}
152
	}
153
	return -1;
153
	return -1;
154
}
154
}
155
 
155
 
156
- (NSInteger)registerFoldedRange:(NSRange)range
156
- (NSInteger)registerFoldedRange:(NSRange)range
157
{
157
{
158
 
158
 
159
 
159
 
160
	[[selfDelegate undoManager] disableUndoRegistration];
160
	[[selfDelegate undoManager] disableUndoRegistration];
161
 
161
 
162
	NSInteger index = -1;
162
	NSInteger index = -1;
163
	for(NSInteger i = 0; i < R_MAX_FOLDED_ITEMS; i++) {
163
	for(NSInteger i = 0; i < R_MAX_FOLDED_ITEMS; i++) {
164
		if(foldedRanges[i][0] == -1) {
164
		if(foldedRanges[i][0] == -1) {
165
			index = i;
165
			index = i;
166
			foldedRanges[i][0] = (NSInteger)range.location;
166
			foldedRanges[i][0] = (NSInteger)range.location;
167
			foldedRanges[i][1] = (NSInteger)range.length;
167
			foldedRanges[i][1] = (NSInteger)range.length;
168
			foldedRanges[i][2] = (NSInteger)NSMaxRange(range);
168
			foldedRanges[i][2] = (NSInteger)NSMaxRange(range);
169
			foldedCounter++;
169
			foldedCounter++;
170
			if(i > currentMaxFoldedIndex) currentMaxFoldedIndex = i;
170
			if(i > currentMaxFoldedIndex) currentMaxFoldedIndex = i;
171
			SLog(@"RScriptEditorTextStorage:registerFoldedRange %@ at position %d : max index %d", NSStringFromRange(range), i, currentMaxFoldedIndex);
171
			SLog(@"RScriptEditorTextStorage:registerFoldedRange %@ at position %ld : max index %ld", NSStringFromRange(range), (long)i, (long)currentMaxFoldedIndex);
172
			break;
172
			break;
173
		}
173
		}
174
	}
174
	}
175
 
175
 
176
	[[selfDelegate undoManager] enableUndoRegistration];
176
	[[selfDelegate undoManager] enableUndoRegistration];
177
 
177
 
178
	return(index);
178
	return(index);
179
 
179
 
180
}
180
}
181
 
181
 
182
- (BOOL)removeFoldedRangeWithIndex:(NSInteger)index
182
- (BOOL)removeFoldedRangeWithIndex:(NSInteger)index
183
{
183
{
184
 
184
 
185
	BOOL exists = NO;
185
	BOOL exists = NO;
186
	NSRange range;
186
	NSRange range;
187
	
187
	
188
	SLog(@"RScriptEditorTextStorage:removeFoldedRangeWithIndex %d", index);
188
	SLog(@"RScriptEditorTextStorage:removeFoldedRangeWithIndex %ld", (long)index);
189
	
189
	
190
	if(index > -1 && index < R_MAX_FOLDED_ITEMS) {
190
	if(index > -1 && index < R_MAX_FOLDED_ITEMS) {
191
		if(foldedRanges[index][0] > -1 && foldedRanges[index][1] > 0) {
191
		if(foldedRanges[index][0] > -1 && foldedRanges[index][1] > 0) {
192
			range = NSMakeRange(foldedRanges[index][0], foldedRanges[index][1]);
192
			range = NSMakeRange(foldedRanges[index][0], foldedRanges[index][1]);
193
			exists = YES;
193
			exists = YES;
194
		}
194
		}
195
	}
195
	}
196
 
196
 
197
	if(!exists) {
197
	if(!exists) {
198
		[self removeAllFoldedRanges];
198
		[self removeAllFoldedRanges];
199
		NSLog(@"Removing folded text chunk failed. For safety reasons all folded chunks were be unfolded.");
199
		NSLog(@"Removing folded text chunk failed. For safety reasons all folded chunks were be unfolded.");
200
		return NO;
200
		return NO;
201
	}
201
	}
202
 
202
 
203
	[[selfDelegate undoManager] disableUndoRegistration];
203
	[[selfDelegate undoManager] disableUndoRegistration];
204
 
204
 
205
	range = NSIntersectionRange(NSMakeRange(0, [[_attributedString string] length]), range);
205
	range = NSIntersectionRange(NSMakeRange(0, [[_attributedString string] length]), range);
206
	if(range.length) {
206
	if(range.length) {
207
		[self removeAttribute:NSCursorAttributeName range:range];
207
		[self removeAttribute:NSCursorAttributeName range:range];
208
		[self removeAttribute:NSToolTipAttributeName range:range];
208
		[self removeAttribute:NSToolTipAttributeName range:range];
209
	}
209
	}
210
 
210
 
211
	foldedRanges[index][0] = -1;
211
	foldedRanges[index][0] = -1;
212
	foldedRanges[index][1] = 0;
212
	foldedRanges[index][1] = 0;
213
	foldedRanges[index][2] = 0;
213
	foldedRanges[index][2] = 0;
214
	foldedCounter--;
214
	foldedCounter--;
215
	if(foldedCounter < 0) foldedCounter = 0;
215
	if(foldedCounter < 0) foldedCounter = 0;
216
 
216
 
217
	// check folded chunks inside range
217
	// check folded chunks inside range
218
	NSInteger rloc = range.location;
218
	NSInteger rloc = range.location;
219
	NSInteger maxrlen = NSMaxRange(range);
219
	NSInteger maxrlen = NSMaxRange(range);
220
	NSRange r;
220
	NSRange r;
221
	for(NSInteger j = currentMaxFoldedIndex; j >= 0; j--) {
221
	for(NSInteger j = currentMaxFoldedIndex; j >= 0; j--) {
222
		if(foldedRanges[j][0] > rloc && foldedRanges[j][2] < maxrlen) {
222
		if(foldedRanges[j][0] > rloc && foldedRanges[j][2] < maxrlen) {
223
			r = NSMakeRange(foldedRanges[j][0], foldedRanges[j][1]);
223
			r = NSMakeRange(foldedRanges[j][0], foldedRanges[j][1]);
224
			foldedRanges[j][0] = -1;
224
			foldedRanges[j][0] = -1;
225
			foldedRanges[j][1] = 0;
225
			foldedRanges[j][1] = 0;
226
			foldedRanges[j][2] = 0;
226
			foldedRanges[j][2] = 0;
227
			[selfDelegate refoldLinesInRange:r];
227
			[selfDelegate refoldLinesInRange:r];
228
		}
228
		}
229
	}
229
	}
230
 
230
 
231
	[[selfDelegate undoManager] enableUndoRegistration];
231
	[[selfDelegate undoManager] enableUndoRegistration];
232
	
232
	
233
	// update currentMaxFoldedIndex
233
	// update currentMaxFoldedIndex
234
	NSInteger maxCount = -1;
234
	NSInteger maxCount = -1;
235
	for(NSInteger i = 0; i < R_MAX_FOLDED_ITEMS; i++) {
235
	for(NSInteger i = 0; i < R_MAX_FOLDED_ITEMS; i++) {
236
		if(foldedRanges[i][0] > -1) {
236
		if(foldedRanges[i][0] > -1) {
237
			if(i > maxCount) maxCount = i;
237
			if(i > maxCount) maxCount = i;
238
		}
238
		}
239
	}
239
	}
240
	currentMaxFoldedIndex = maxCount;
240
	currentMaxFoldedIndex = maxCount;
241
	SLog(@"RScriptEditorTextStorage:removeFoldedRangeWithIndex: done. Max index: %d", currentMaxFoldedIndex);
241
	SLog(@"RScriptEditorTextStorage:removeFoldedRangeWithIndex: done. Max index: %ld", (long) currentMaxFoldedIndex);
242
 
242
 
243
	return YES;
243
	return YES;
244
}
244
}
245
 
245
 
246
- (void)removeAllFoldedRanges
246
- (void)removeAllFoldedRanges
247
{
247
{
248
 
248
 
249
	[[selfDelegate undoManager] disableUndoRegistration];
249
	[[selfDelegate undoManager] disableUndoRegistration];
250
 
250
 
251
	for(NSInteger i = 0; i < R_MAX_FOLDED_ITEMS; i++) {
251
	for(NSInteger i = 0; i < R_MAX_FOLDED_ITEMS; i++) {
252
		foldedRanges[i][0] = -1;
252
		foldedRanges[i][0] = -1;
253
		foldedRanges[i][1] = 0;
253
		foldedRanges[i][1] = 0;
254
		foldedRanges[i][2] = 0;
254
		foldedRanges[i][2] = 0;
255
	}
255
	}
256
	NSRange range = NSMakeRange(0, [_attributedString length]);
256
	NSRange range = NSMakeRange(0, [_attributedString length]);
257
	[self removeAttribute:NSCursorAttributeName range:range];
257
	[self removeAttribute:NSCursorAttributeName range:range];
258
	[self removeAttribute:NSToolTipAttributeName range:range];
258
	[self removeAttribute:NSToolTipAttributeName range:range];
259
 
259
 
260
	foldedCounter = 0;
260
	foldedCounter = 0;
261
	currentMaxFoldedIndex = -1;
261
	currentMaxFoldedIndex = -1;
262
 
262
 
263
	[[selfDelegate undoManager] enableUndoRegistration];
263
	[[selfDelegate undoManager] enableUndoRegistration];
264
 
264
 
265
}
265
}
266
 
266
 
267
- (BOOL)existsFoldedRange:(NSRange)range
267
- (BOOL)existsFoldedRange:(NSRange)range
268
{
268
{
269
 
269
 
270
	if(!foldedCounter) return NO;
270
	if(!foldedCounter) return NO;
271
 
271
 
272
	BOOL success = NO;
272
	BOOL success = NO;
273
	for(NSInteger i = 0; i < currentMaxFoldedIndex+1; i++) {
273
	for(NSInteger i = 0; i < currentMaxFoldedIndex+1; i++) {
274
		if(foldedRanges[i][0] == range.location && foldedRanges[i][1] == range.length) {
274
		if(foldedRanges[i][0] == range.location && foldedRanges[i][1] == range.length) {
275
			success = YES;
275
			success = YES;
276
			break;
276
			break;
277
		}
277
		}
278
	}
278
	}
279
 
279
 
280
	return success;
280
	return success;
281
	
281
	
282
}
282
}
283
 
283
 
284
- (NSRange)foldedRangeAtIndex:(NSInteger)index
284
- (NSRange)foldedRangeAtIndex:(NSInteger)index
285
{
285
{
286
 
286
 
287
	if(!foldedCounter || index < 0 || index > R_MAX_FOLDED_ITEMS) return NSMakeRange(NSNotFound, 0);
287
	if(!foldedCounter || index < 0 || index > R_MAX_FOLDED_ITEMS) return NSMakeRange(NSNotFound, 0);
288
 
288
 
289
	NSInteger loc = foldedRanges[index][0];
289
	NSInteger loc = foldedRanges[index][0];
290
 
290
 
291
	if(loc == -1) return NSMakeRange(NSNotFound, 0);
291
	if(loc == -1) return NSMakeRange(NSNotFound, 0);
292
 
292
 
293
	return NSMakeRange(loc, foldedRanges[index][1]);
293
	return NSMakeRange(loc, foldedRanges[index][1]);
294
 
294
 
295
}
295
}
296
#pragma mark -
296
#pragma mark -
297
#pragma mark Primitives
297
#pragma mark Primitives
298
 
298
 
299
- (NSString *)string
299
- (NSString *)string
300
{ 
300
{ 
301
    return _attributedString ? [_attributedString string] : nil;
301
    return _attributedString ? [_attributedString string] : nil;
302
}
302
}
303
 
303
 
304
- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range
304
- (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range
305
{
305
{
306
 
306
 
307
    NSDictionary *attributes = [_attributedString attributesAtIndex:location effectiveRange:range];
307
    NSDictionary *attributes = [_attributedString attributesAtIndex:location effectiveRange:range];
308
 
308
 
309
	if(!foldedCounter || location > [_attributedString length]) return attributes;
309
	if(!foldedCounter || location > [_attributedString length]) return attributes;
310
 
310
 
311
	NSRange effectiveRange;
311
	NSRange effectiveRange;
312
 
312
 
313
	// Check if location is inside folded range for drawing indicator
313
	// Check if location is inside folded range for drawing indicator
314
	NSInteger index = -1;
314
	NSInteger index = -1;
315
	if(location) {
315
	if(location) {
316
		// Notes folded ranges are stored from { to } but indicator will drawn inside of { and }
316
		// Notes folded ranges are stored from { to } but indicator will drawn inside of { and }
317
		NSInteger adjLocation = location + 2;
317
		NSInteger adjLocation = location + 2;
318
		for(NSInteger i = 0; i < currentMaxFoldedIndex+1; i++) {
318
		for(NSInteger i = 0; i < currentMaxFoldedIndex+1; i++) {
319
			if(foldedRanges[i][2] > adjLocation && foldedRanges[i][0] < location) {
319
			if(foldedRanges[i][2] > adjLocation && foldedRanges[i][0] < location) {
320
				index = i;
320
				index = i;
321
				break;
321
				break;
322
			}
322
			}
323
		}
323
		}
324
	}
324
	}
325
 
325
 
326
	if (index > -1) {
326
	if (index > -1) {
327
		effectiveRange = NSMakeRange(foldedRanges[index][0]+1, foldedRanges[index][1]-2);
327
		effectiveRange = NSMakeRange(foldedRanges[index][0]+1, foldedRanges[index][1]-2);
328
		// We adds NSAttachmentAttributeName if location is at beginning of folded range
328
		// We adds NSAttachmentAttributeName if location is at beginning of folded range
329
		if (location == effectiveRange.location) { // beginning of a folded range
329
		if (location == effectiveRange.location) { // beginning of a folded range
330
 
330
 
331
			NSMutableDictionary *dict = [attributes mutableCopyWithZone:NULL];
331
			NSMutableDictionary *dict = [attributes mutableCopyWithZone:NULL];
332
			[dict setObject:sharedAttachment forKey:NSAttachmentAttributeName];
332
			[dict setObject:sharedAttachment forKey:NSAttachmentAttributeName];
333
			attributes = [dict autorelease];
333
			attributes = [dict autorelease];
334
			effectiveRange.length = 1;
334
			effectiveRange.length = 1;
335
 
335
 
336
		} else {
336
		} else {
337
			++(effectiveRange.location); --(effectiveRange.length);
337
			++(effectiveRange.location); --(effectiveRange.length);
338
		}
338
		}
339
		effectiveRange = NSIntersectionRange(effectiveRange, NSMakeRange(0, [_attributedString length]));
339
		effectiveRange = NSIntersectionRange(effectiveRange, NSMakeRange(0, [_attributedString length]));
340
		if (range) *range = effectiveRange;
340
		if (range) *range = effectiveRange;
341
	}
341
	}
342
 
342
 
343
	return attributes;
343
	return attributes;
344
 
344
 
345
}
345
}
346
 
346
 
347
- (void)edited:(NSUInteger)mask range:(NSRange)oldRange changeInLength:(NSInteger)lengthChange
347
- (void)edited:(NSTextStorageEditActions)mask range:(NSRange)oldRange changeInLength:(NSInteger)lengthChange
348
{
348
{
349
 
349
 
350
	if(foldedCounter && mask == NSTextStorageEditedCharacters) {
350
	if(foldedCounter && mask == NSTextStorageEditedCharacters) {
351
		// update foldedRanges array due to changes
351
		// update foldedRanges array due to changes
352
		NSInteger index = oldRange.location-1;
352
		NSInteger index = oldRange.location-1;
353
		NSInteger maxOldRange = NSMaxRange(oldRange) + 1;
353
		NSInteger maxOldRange = NSMaxRange(oldRange) + 1;
354
		for(NSInteger i = 0; i < currentMaxFoldedIndex+1; i++) {
354
		for(NSInteger i = 0; i < currentMaxFoldedIndex+1; i++) {
355
			if(index < foldedRanges[i][0]) {
355
			if(index < foldedRanges[i][0]) {
356
				// if change covers the entire folded range -> delete it
356
				// if change covers the entire folded range -> delete it
357
				if(foldedRanges[i][2] < maxOldRange && foldedRanges[i][0] > index) {
357
				if(foldedRanges[i][2] < maxOldRange && foldedRanges[i][0] > index) {
358
					[self removeFoldedRangeWithIndex:i];
358
					[self removeFoldedRangeWithIndex:i];
359
					continue;
359
					continue;
360
				}
360
				}
361
				// otherwise correct folded start range and maxrange
361
				// otherwise correct folded start range and maxrange
362
				foldedRanges[i][0] += lengthChange;
362
				foldedRanges[i][0] += lengthChange;
363
				foldedRanges[i][2] += lengthChange;
363
				foldedRanges[i][2] += lengthChange;
364
				// for safety delete it if new location is negative
364
				// for safety delete it if new location is negative
365
				if(foldedRanges[i][0] < 0) {
365
				if(foldedRanges[i][0] < 0) {
366
					[self removeFoldedRangeWithIndex:i];
366
					[self removeFoldedRangeWithIndex:i];
367
				}
367
				}
368
			}
368
			}
369
		}
369
		}
370
	}
370
	}
371
 
371
 
372
	[super edited:mask range:oldRange changeInLength:lengthChange];
372
	[super edited:mask range:oldRange changeInLength:lengthChange];
373
}
373
}
374
 
374
 
375
// NSMutableAttributedString primitives
375
// NSMutableAttributedString primitives
376
- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str
376
- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str
377
{
377
{
378
    [_attributedString replaceCharactersInRange:range withString:str];
378
    [_attributedString replaceCharactersInRange:range withString:str];
379
    [self edited:NSTextStorageEditedCharacters range:range changeInLength: [str length] - range.length];
379
    [self edited:NSTextStorageEditedCharacters range:range changeInLength: [str length] - range.length];
380
}
380
}
381
 
381
 
382
- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range
382
- (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range
383
{
383
{
384
    [_attributedString setAttributes:attrs range:range];
384
    [_attributedString setAttributes:attrs range:range];
385
    [self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
385
    [self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
386
}
386
}
387
 
387
 
388
// Attribute Fixing Overrides
388
// Attribute Fixing Overrides
389
/*
389
/*
390
- (void)fixAttributesInRange:(NSRange)range
390
- (void)fixAttributesInRange:(NSRange)range
391
{
391
{
392
	[super fixAttributesInRange:range];
392
	[super fixAttributesInRange:range];
393
 
393
 
394
	if(NSMaxRange(range) == 0) return;
394
	if(NSMaxRange(range) == 0) return;
395
 
395
 
396
	//	we want to avoid extending to the last paragraph separator
396
	//	we want to avoid extending to the last paragraph separator
397
	NSDictionary *attributeDict;
397
	NSDictionary *attributeDict;
398
	NSRange effectiveRange = { 0, 0 };
398
	NSRange effectiveRange = { 0, 0 };
399
	NSUInteger idx = range.location;
399
	NSUInteger idx = range.location;
400
	while (NSMaxRange(effectiveRange) < NSMaxRange(range)) {
400
	while (NSMaxRange(effectiveRange) < NSMaxRange(range)) {
401
		attributeDict = [_attributedString attributesAtIndex:idx
401
		attributeDict = [_attributedString attributesAtIndex:idx
402
								   longestEffectiveRange:&effectiveRange
402
								   longestEffectiveRange:&effectiveRange
403
												 inRange:range];
403
												 inRange:range];
404
		id value = [attributeDict objectForKey:foldingAttributeName];
404
		id value = [attributeDict objectForKey:foldingAttributeName];
405
		if (value && effectiveRange.length) {
405
		if (value && effectiveRange.length) {
406
			NSUInteger paragraphStart, paragraphEnd, contentsEnd;
406
			NSUInteger paragraphStart, paragraphEnd, contentsEnd;
407
			[[self string] getParagraphStart:&paragraphStart end:&paragraphEnd contentsEnd:&contentsEnd forRange:range];
407
			[[self string] getParagraphStart:&paragraphStart end:&paragraphEnd contentsEnd:&contentsEnd forRange:range];
408
			if ((NSMaxRange(range) == paragraphEnd) && (contentsEnd < paragraphEnd)) {
408
			if ((NSMaxRange(range) == paragraphEnd) && (contentsEnd < paragraphEnd)) {
409
				[self removeAttribute:foldingAttributeName range:NSMakeRange(contentsEnd, paragraphEnd - contentsEnd)];
409
				[self removeAttribute:foldingAttributeName range:NSMakeRange(contentsEnd, paragraphEnd - contentsEnd)];
410
			}
410
			}
411
		}
411
		}
412
		idx = NSMaxRange(effectiveRange);
412
		idx = NSMaxRange(effectiveRange);
413
	}
413
	}
414
 
414
 
415
	// 10.6 implementation
415
	// 10.6 implementation
416
	// [self enumerateAttribute:lineFoldingAttributeName inRange:range options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
416
	// [self enumerateAttribute:lineFoldingAttributeName inRange:range options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
417
	// 	if (value && (range.length > 1)) {
417
	// 	if (value && (range.length > 1)) {
418
	// 		NSUInteger paragraphStart, paragraphEnd, contentsEnd;
418
	// 		NSUInteger paragraphStart, paragraphEnd, contentsEnd;
419
	// 		[[self string] getParagraphStart:&paragraphStart end:&paragraphEnd contentsEnd:&contentsEnd forRange:range];
419
	// 		[[self string] getParagraphStart:&paragraphStart end:&paragraphEnd contentsEnd:&contentsEnd forRange:range];
420
	// 		if ((NSMaxRange(range) == paragraphEnd) && (contentsEnd < paragraphEnd)) {
420
	// 		if ((NSMaxRange(range) == paragraphEnd) && (contentsEnd < paragraphEnd)) {
421
	// 			[self removeAttribute:lineFoldingAttributeName range:NSMakeRange(contentsEnd, paragraphEnd - contentsEnd)];
421
	// 			[self removeAttribute:lineFoldingAttributeName range:NSMakeRange(contentsEnd, paragraphEnd - contentsEnd)];
422
	// 		}
422
	// 		}
423
	// 	}
423
	// 	}
424
	// }];
424
	// }];
425
}
425
}
426
*/
426
*/
427
 
427
 
428
@end
428
@end