The R Project SVN R-packages

Rev

Rev 6274 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6274 Rev 7293
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-5  The R Foundation
5
 *                     Copyright (C) 2004-5  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
 *  RScriptEditorTextView.m
29
 *  RScriptEditorTextView.m
30
 *
30
 *
31
 *  Created by Hans-J. Bibiko on 15/02/2011.
31
 *  Created by Hans-J. Bibiko on 15/02/2011.
32
 *
32
 *
33
 */
33
 */
34
 
34
 
35
#import "RScriptEditorTextView.h"
35
#import "RScriptEditorTextView.h"
36
#import "RScriptEditorTextStorage.h"
36
#import "RScriptEditorTextStorage.h"
37
#import "RScriptEditorTypeSetter.h"
37
#import "RScriptEditorTypeSetter.h"
38
#import "RScriptEditorLayoutManager.h"
38
#import "RScriptEditorLayoutManager.h"
39
#import "RGUI.h"
39
#import "RGUI.h"
40
#import "Tools/RTooltip.h"
40
#import "Tools/RTooltip.h"
41
 
41
 
42
 
42
 
43
#pragma mark -
43
#pragma mark -
44
#pragma mark flex init
44
#pragma mark flex init
45
 
45
 
46
/**
46
/**
47
 * Include all the extern variables and prototypes required for flex (used for syntax highlighting)
47
 * Include all the extern variables and prototypes required for flex (used for syntax highlighting)
48
 */
48
 */
49
 
49
 
50
#import "RScriptEditorTokens.h"
50
#import "RScriptEditorTokens.h"
51
#import "RdScriptEditorTokens.h"
51
#import "RdScriptEditorTokens.h"
52
 
52
 
53
// R lexer
53
// R lexer
54
extern NSUInteger yylex();
54
extern NSUInteger yylex();
55
extern NSUInteger yyuoffset, yyuleng;
55
extern NSUInteger yyuoffset, yyuleng;
56
typedef struct yy_buffer_state *YY_BUFFER_STATE;
56
typedef struct yy_buffer_state *YY_BUFFER_STATE;
57
void yy_switch_to_buffer(YY_BUFFER_STATE);
57
void yy_switch_to_buffer(YY_BUFFER_STATE);
58
YY_BUFFER_STATE yy_scan_string (const char *);
58
YY_BUFFER_STATE yy_scan_string (const char *);
59
 
59
 
60
// Rd lexer
60
// Rd lexer
61
extern NSUInteger rdlex();
61
extern NSUInteger rdlex();
62
typedef struct rd_buffer_state *RD_BUFFER_STATE;
62
typedef struct rd_buffer_state *RD_BUFFER_STATE;
63
void rd_switch_to_buffer(RD_BUFFER_STATE);
63
void rd_switch_to_buffer(RD_BUFFER_STATE);
64
RD_BUFFER_STATE rd_scan_string (const char *);
64
RD_BUFFER_STATE rd_scan_string (const char *);
65
 
65
 
66
static SEL _foldedSel;
66
static SEL _foldedSel;
67
 
67
 
68
#pragma mark -
68
#pragma mark -
69
#pragma mark attribute definition 
69
#pragma mark attribute definition 
70
 
70
 
71
#define kAPlinked      @"Linked" // attribute for a via auto-pair inserted char
71
#define kAPlinked      @"Linked" // attribute for a via auto-pair inserted char
72
#define kAPval         @"linked"
72
#define kAPval         @"linked"
73
#define kLEXToken      @"Quoted" // set via lex to indicate a quoted string
73
#define kLEXToken      @"Quoted" // set via lex to indicate a quoted string
74
#define kLEXTokenValue @"isMarked"
74
#define kLEXTokenValue @"isMarked"
75
#define kRkeyword      @"s"      // attribute for found R keywords
75
#define kRkeyword      @"s"      // attribute for found R keywords
76
#define kQuote         @"Quote"
76
#define kQuote         @"Quote"
77
#define kQuoteValue    @"isQuoted"
77
#define kQuoteValue    @"isQuoted"
78
#define kValue         @"x"
78
#define kValue         @"x"
79
#define kBTQuote       @"BTQuote"
79
#define kBTQuote       @"BTQuote"
80
#define kBTQuoteValue  @"isBTQuoted"
80
#define kBTQuoteValue  @"isBTQuoted"
81
 
81
 
82
#pragma mark -
82
#pragma mark -
83
 
83
 
84
#define R_SYNTAX_HILITE_BIAS 2000
84
#define R_SYNTAX_HILITE_BIAS 2000
85
#define R_MAX_TEXT_SIZE_FOR_SYNTAX_HIGHLIGHTING 20000000
85
#define R_MAX_TEXT_SIZE_FOR_SYNTAX_HIGHLIGHTING 20000000
86
 
86
 
87
 
87
 
88
static inline const char* NSStringUTF8String(NSString* self) 
88
static inline const char* NSStringUTF8String(NSString* self) 
89
{
89
{
90
	typedef const char* (*SPUTF8StringMethodPtr)(NSString*, SEL);
90
	typedef const char* (*SPUTF8StringMethodPtr)(NSString*, SEL);
91
	static SPUTF8StringMethodPtr SPNSStringGetUTF8String;
91
	static SPUTF8StringMethodPtr SPNSStringGetUTF8String;
92
	if (!SPNSStringGetUTF8String) SPNSStringGetUTF8String = (SPUTF8StringMethodPtr)[NSString instanceMethodForSelector:@selector(UTF8String)];
92
	if (!SPNSStringGetUTF8String) SPNSStringGetUTF8String = (SPUTF8StringMethodPtr)[NSString instanceMethodForSelector:@selector(UTF8String)];
93
	const char* to_return = SPNSStringGetUTF8String(self, @selector(UTF8String));
93
	const char* to_return = SPNSStringGetUTF8String(self, @selector(UTF8String));
94
	return to_return;
94
	return to_return;
95
}
95
}
96
 
96
 
97
static inline void NSMutableAttributedStringAddAttributeValueRange (NSMutableAttributedString* self, NSString* aStr, id aValue, NSRange aRange) 
97
static inline void NSMutableAttributedStringAddAttributeValueRange (NSMutableAttributedString* self, NSString* aStr, id aValue, NSRange aRange) 
98
{
98
{
99
	typedef void (*SPMutableAttributedStringAddAttributeValueRangeMethodPtr)(NSMutableAttributedString*, SEL, NSString*, id, NSRange);
99
	typedef void (*SPMutableAttributedStringAddAttributeValueRangeMethodPtr)(NSMutableAttributedString*, SEL, NSString*, id, NSRange);
100
	static SPMutableAttributedStringAddAttributeValueRangeMethodPtr SPMutableAttributedStringAddAttributeValueRange;
100
	static SPMutableAttributedStringAddAttributeValueRangeMethodPtr SPMutableAttributedStringAddAttributeValueRange;
101
	if (!SPMutableAttributedStringAddAttributeValueRange) SPMutableAttributedStringAddAttributeValueRange = (SPMutableAttributedStringAddAttributeValueRangeMethodPtr)[self methodForSelector:@selector(addAttribute:value:range:)];
101
	if (!SPMutableAttributedStringAddAttributeValueRange) SPMutableAttributedStringAddAttributeValueRange = (SPMutableAttributedStringAddAttributeValueRangeMethodPtr)[self methodForSelector:@selector(addAttribute:value:range:)];
102
	SPMutableAttributedStringAddAttributeValueRange(self, @selector(addAttribute:value:range:), aStr, aValue, aRange);
102
	SPMutableAttributedStringAddAttributeValueRange(self, @selector(addAttribute:value:range:), aStr, aValue, aRange);
103
	return;
103
	return;
104
}
104
}
105
 
105
 
106
static inline id NSMutableAttributedStringAttributeAtIndex (NSMutableAttributedString* self, NSString* aStr, NSUInteger index, NSRangePointer range) 
106
static inline id NSMutableAttributedStringAttributeAtIndex (NSMutableAttributedString* self, NSString* aStr, NSUInteger index, NSRangePointer range) 
107
{
107
{
108
	typedef id (*SPMutableAttributedStringAttributeAtIndexMethodPtr)(NSMutableAttributedString*, SEL, NSString*, NSUInteger, NSRangePointer);
108
	typedef id (*SPMutableAttributedStringAttributeAtIndexMethodPtr)(NSMutableAttributedString*, SEL, NSString*, NSUInteger, NSRangePointer);
109
	static SPMutableAttributedStringAttributeAtIndexMethodPtr SPMutableAttributedStringAttributeAtIndex;
109
	static SPMutableAttributedStringAttributeAtIndexMethodPtr SPMutableAttributedStringAttributeAtIndex;
110
	if (!SPMutableAttributedStringAttributeAtIndex) SPMutableAttributedStringAttributeAtIndex = (SPMutableAttributedStringAttributeAtIndexMethodPtr)[self methodForSelector:@selector(attribute:atIndex:effectiveRange:)];
110
	if (!SPMutableAttributedStringAttributeAtIndex) SPMutableAttributedStringAttributeAtIndex = (SPMutableAttributedStringAttributeAtIndexMethodPtr)[self methodForSelector:@selector(attribute:atIndex:effectiveRange:)];
111
	id r = SPMutableAttributedStringAttributeAtIndex(self, @selector(attribute:atIndex:effectiveRange:), aStr, index, range);
111
	id r = SPMutableAttributedStringAttributeAtIndex(self, @selector(attribute:atIndex:effectiveRange:), aStr, index, range);
112
	return r;
112
	return r;
113
}
113
}
114
 
114
 
115
 
115
 
116
@implementation RScriptEditorTextView
116
@implementation RScriptEditorTextView
117
 
117
 
118
- (void)awakeFromNib
118
- (void)awakeFromNib
119
{
119
{
120
 
120
 
121
	// we are a subclass of RTextView which has its own awake and we must call it
121
	// we are a subclass of RTextView which has its own awake and we must call it
122
	[super awakeFromNib];
122
	[super awakeFromNib];
123
 
123
 
124
	SLog(@"RScriptEditorTextView: awakeFromNib <%@>", self);
124
	SLog(@"RScriptEditorTextView: awakeFromNib <%@>", self);
125
 
125
 
126
	selfDelegate = (RDocumentWinCtrl*)[self delegate];
126
	selfDelegate = (RDocumentWinCtrl*)[self delegate];
127
 
127
 
128
	breakSyntaxHighlighting = 0;
128
	breakSyntaxHighlighting = 0;
129
	_foldedSel = @selector(foldedAtIndex:);
129
	_foldedSel = @selector(foldedAtIndex:);
130
	
130
	
131
	// Bind scrollView programmatically - if done in RDocument.xib this'd lead to
131
	// Bind scrollView programmatically - if done in RDocument.xib this'd lead to
132
	// calling awakeFromNib twice
132
	// calling awakeFromNib twice
133
	id scrView = (NSScrollView *)self.superview.superview;
133
	id scrView = (NSScrollView *)self.superview.superview;
134
	if ([scrView isKindOfClass:[NSScrollView class]]) {
134
	if ([scrView isKindOfClass:[NSScrollView class]]) {
135
		if(scrollView) [scrollView release];
135
		if(scrollView) [scrollView release];
136
		scrollView = [scrView retain];
136
		scrollView = [scrView retain];
137
		SLog(@"RScriptEditorTextView:awakeFromNib set scrollView");
137
		SLog(@"RScriptEditorTextView:awakeFromNib set scrollView");
138
	}
138
	}
139
 
139
 
140
	prefs = [[NSUserDefaults standardUserDefaults] retain];
140
	prefs = [[NSUserDefaults standardUserDefaults] retain];
141
	[[Preferences sharedPreferences] addDependent:self];
141
	[[Preferences sharedPreferences] addDependent:self];
142
 
142
 
143
	lineNumberingEnabled = [Preferences flagForKey:showLineNumbersKey withDefault:NO];
143
	lineNumberingEnabled = [Preferences flagForKey:showLineNumbersKey withDefault:NO];
144
 
144
 
145
	// Init textStorage and set self as delegate for the textView's textStorage to enable
145
	// Init textStorage and set self as delegate for the textView's textStorage to enable
146
	// syntax highlighting, folding etc.
146
	// syntax highlighting, folding etc.
147
	theTextStorage = [[RScriptEditorTextStorage alloc] initWithDelegate:self];
147
	theTextStorage = [[RScriptEditorTextStorage alloc] initWithDelegate:self];
148
 
148
 
149
	_foldedImp = [theTextStorage methodForSelector:_foldedSel];
149
	_foldedImp = [theTextStorage methodForSelector:_foldedSel];
150
 
150
 
151
	// Make sure using foldingLayoutManager
151
	// Make sure using foldingLayoutManager
152
	if (![[self layoutManager] isKindOfClass:[RScriptEditorLayoutManager class]]) {
152
	if (![[self layoutManager] isKindOfClass:[RScriptEditorLayoutManager class]]) {
153
		RScriptEditorLayoutManager *layoutManager = [[RScriptEditorLayoutManager alloc] init];
153
		RScriptEditorLayoutManager *layoutManager = [[RScriptEditorLayoutManager alloc] init];
154
		[[self textContainer] replaceLayoutManager:layoutManager];
154
		[[self textContainer] replaceLayoutManager:layoutManager];
155
		[layoutManager release];
155
		[layoutManager release];
156
	}
156
	}
157
 
157
 
158
	// disabled to get the current text range in textView safer
158
	// disabled to get the current text range in textView safer
159
	[[self layoutManager] setBackgroundLayoutEnabled:NO];
159
	[[self layoutManager] setBackgroundLayoutEnabled:NO];
160
	[[self layoutManager] replaceTextStorage:theTextStorage];
160
	[[self layoutManager] replaceTextStorage:theTextStorage];
161
 
161
 
162
	[(RScriptEditorTypeSetter*)[[self layoutManager] typesetter] setTextStorage:theTextStorage];
162
	[(RScriptEditorTypeSetter*)[[self layoutManager] typesetter] setTextStorage:theTextStorage];
163
 
163
 
164
	isSyntaxHighlighting = NO;
164
	isSyntaxHighlighting = NO;
165
 
165
 
166
	if([prefs objectForKey:highlightCurrentLine] == nil) [prefs setBool:YES forKey:highlightCurrentLine];
166
	if([prefs objectForKey:highlightCurrentLine] == nil) [prefs setBool:YES forKey:highlightCurrentLine];
167
	if([prefs objectForKey:indentNewLines] == nil) [prefs setBool:YES forKey:indentNewLines];
167
	if([prefs objectForKey:indentNewLines] == nil) [prefs setBool:YES forKey:indentNewLines];
168
 
168
 
169
	[self setFont:[Preferences unarchivedObjectForKey:RScriptEditorDefaultFont withDefault:[NSFont fontWithName:@"Monaco" size:11]]];
169
	[self setFont:[Preferences unarchivedObjectForKey:RScriptEditorDefaultFont withDefault:[NSFont fontWithName:@"Monaco" size:11]]];
170
 
170
 
171
	// Set defaults for general usage
171
	// Set defaults for general usage
172
	braceHighlightInterval = [Preferences floatForKey:HighlightIntervalKey withDefault:0.3f];
172
	braceHighlightInterval = [Preferences floatForKey:HighlightIntervalKey withDefault:0.3f];
173
	argsHints = [Preferences flagForKey:prefShowArgsHints withDefault:YES];
173
	argsHints = [Preferences flagForKey:prefShowArgsHints withDefault:YES];
174
	lineWrappingEnabled = [Preferences flagForKey:enableLineWrappingKey withDefault:YES];
174
	lineWrappingEnabled = [Preferences flagForKey:enableLineWrappingKey withDefault:YES];
175
	syntaxHighlightingEnabled = [Preferences flagForKey:showSyntaxColoringKey withDefault:YES];
175
	syntaxHighlightingEnabled = [Preferences flagForKey:showSyntaxColoringKey withDefault:YES];
176
 
176
 
177
	deleteBackward = NO;
177
	deleteBackward = NO;
178
	startListeningToBoundChanges = NO;
178
	startListeningToBoundChanges = NO;
179
	currentHighlight = -1;
179
	currentHighlight = -1;
180
 
180
 
181
	// For now replaced selectedTextBackgroundColor by redColor
181
	// For now replaced selectedTextBackgroundColor by redColor
182
	highlightColorAttr = [[NSDictionary alloc] initWithObjectsAndKeys:[NSColor redColor], NSBackgroundColorAttributeName, nil];
182
	highlightColorAttr = [[NSDictionary alloc] initWithObjectsAndKeys:[NSColor redColor], NSBackgroundColorAttributeName, nil];
183
 
183
 
184
	if([selfDelegate isRdDocument])
184
	if([selfDelegate isRdDocument])
185
		editorToolbar = [[RdEditorToolbar alloc] initWithEditor:selfDelegate];
185
		editorToolbar = [[RdEditorToolbar alloc] initWithEditor:selfDelegate];
186
	else
186
	else
187
		editorToolbar = [[REditorToolbar alloc] initWithEditor:selfDelegate];
187
		editorToolbar = [[REditorToolbar alloc] initWithEditor:selfDelegate];
188
 
188
 
189
	[self setAllowsDocumentBackgroundColorChange:YES];
189
	[self setAllowsDocumentBackgroundColorChange:YES];
190
	[self setContinuousSpellCheckingEnabled:NO];
190
	[self setContinuousSpellCheckingEnabled:NO];
191
 
191
 
192
	if(![Preferences flagForKey:enableLineWrappingKey withDefault: YES])
192
	if(![Preferences flagForKey:enableLineWrappingKey withDefault: YES])
193
		[scrollView setHasHorizontalScroller:YES];
193
		[scrollView setHasHorizontalScroller:YES];
194
 
194
 
195
	if(!lineWrappingEnabled)
195
	if(!lineWrappingEnabled)
196
		[self updateLineWrappingMode];
196
		[self updateLineWrappingMode];
197
 
197
 
198
	// Re-define tab stops for a better editing
198
	// Re-define tab stops for a better editing
199
	[self setTabStops];
199
	[self setTabStops];
200
 
200
 
201
	NSColor *c = [Preferences unarchivedObjectForKey:normalSyntaxColorKey withDefault:nil];
201
	NSColor *c = [Preferences unarchivedObjectForKey:normalSyntaxColorKey withDefault:nil];
202
	if (c) shColorNormal = c;
202
	if (c) shColorNormal = c;
203
	else shColorNormal=[NSColor colorWithDeviceRed:0.025 green:0.085 blue:0.600 alpha:1.0];
203
	else shColorNormal=[NSColor colorWithDeviceRed:0.025 green:0.085 blue:0.600 alpha:1.0];
204
	[shColorNormal retain];
204
	[shColorNormal retain];
205
 
205
 
206
	c=[Preferences unarchivedObjectForKey:stringSyntaxColorKey withDefault:nil];
206
	c=[Preferences unarchivedObjectForKey:stringSyntaxColorKey withDefault:nil];
207
	if (c) shColorString = c;
207
	if (c) shColorString = c;
208
	else shColorString=[NSColor colorWithDeviceRed:0.690 green:0.075 blue:0.000 alpha:1.0];
208
	else shColorString=[NSColor colorWithDeviceRed:0.690 green:0.075 blue:0.000 alpha:1.0];
209
	[shColorString retain];	
209
	[shColorString retain];	
210
 
210
 
211
	c=[Preferences unarchivedObjectForKey:numberSyntaxColorKey withDefault:nil];
211
	c=[Preferences unarchivedObjectForKey:numberSyntaxColorKey withDefault:nil];
212
	if (c) shColorNumber = c;
212
	if (c) shColorNumber = c;
213
	else shColorNumber=[NSColor colorWithDeviceRed:0.020 green:0.320 blue:0.095 alpha:1.0];
213
	else shColorNumber=[NSColor colorWithDeviceRed:0.020 green:0.320 blue:0.095 alpha:1.0];
214
	[shColorNumber retain];
214
	[shColorNumber retain];
215
 
215
 
216
	c=[Preferences unarchivedObjectForKey:keywordSyntaxColorKey withDefault:nil];
216
	c=[Preferences unarchivedObjectForKey:keywordSyntaxColorKey withDefault:nil];
217
	if (c) shColorKeyword = c;
217
	if (c) shColorKeyword = c;
218
	else shColorKeyword=[NSColor colorWithDeviceRed:0.765 green:0.535 blue:0.035 alpha:1.0];
218
	else shColorKeyword=[NSColor colorWithDeviceRed:0.765 green:0.535 blue:0.035 alpha:1.0];
219
	[shColorKeyword retain];
219
	[shColorKeyword retain];
220
 
220
 
221
	c=[Preferences unarchivedObjectForKey:commentSyntaxColorKey withDefault:nil];
221
	c=[Preferences unarchivedObjectForKey:commentSyntaxColorKey withDefault:nil];
222
	if (c) shColorComment = c;
222
	if (c) shColorComment = c;
223
	else shColorComment=[NSColor colorWithDeviceRed:0.312 green:0.309 blue:0.309 alpha:1.0];
223
	else shColorComment=[NSColor colorWithDeviceRed:0.312 green:0.309 blue:0.309 alpha:1.0];
224
	[shColorComment retain];
224
	[shColorComment retain];
225
 
225
 
226
	c=[Preferences unarchivedObjectForKey:identifierSyntaxColorKey withDefault:nil];
226
	c=[Preferences unarchivedObjectForKey:identifierSyntaxColorKey withDefault:nil];
227
	if (c) shColorIdentifier = c;
227
	if (c) shColorIdentifier = c;
228
	else shColorIdentifier=[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:1.0];
228
	else shColorIdentifier=[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:1.0];
229
	[shColorIdentifier retain]; 
229
	[shColorIdentifier retain]; 
230
 
230
 
231
	c=[Preferences unarchivedObjectForKey:editorSelectionBackgroundColorKey withDefault:nil];
231
	c=[Preferences unarchivedObjectForKey:editorSelectionBackgroundColorKey withDefault:nil];
232
	if (!c) c=[NSColor colorWithDeviceRed:0.71f green:0.835f blue:1.0f alpha:1.0f];
232
	if (!c) c=[NSColor colorWithDeviceRed:0.71f green:0.835f blue:1.0f alpha:1.0f];
233
	NSMutableDictionary *attr = [NSMutableDictionary dictionary];
233
	NSMutableDictionary *attr = [NSMutableDictionary dictionary];
234
	[attr setDictionary:[self selectedTextAttributes]];
234
	[attr setDictionary:[self selectedTextAttributes]];
235
	[attr setObject:c forKey:NSBackgroundColorAttributeName];
235
	[attr setObject:c forKey:NSBackgroundColorAttributeName];
236
	[self setSelectedTextAttributes:attr];
236
	[self setSelectedTextAttributes:attr];
237
	
237
	
238
	// Rd stuff
238
	// Rd stuff
239
	// c=[Preferences unarchivedObjectForKey:sectionRdSyntaxColorKey withDefault:nil];
239
	// c=[Preferences unarchivedObjectForKey:sectionRdSyntaxColorKey withDefault:nil];
240
	// if (c) rdColorSection = c;
240
	// if (c) rdColorSection = c;
241
	// else rdColorSection=[NSColor colorWithDeviceRed:0.8 green:0.0353 blue:0.02 alpha:1.0];
241
	// else rdColorSection=[NSColor colorWithDeviceRed:0.8 green:0.0353 blue:0.02 alpha:1.0];
242
	// [rdColorSection retain];
242
	// [rdColorSection retain];
243
	// 
243
	// 
244
	// c=[Preferences unarchivedObjectForKey:macroArgRdSyntaxColorKey withDefault:nil];
244
	// c=[Preferences unarchivedObjectForKey:macroArgRdSyntaxColorKey withDefault:nil];
245
	// if (c) rdColorMacroArg = c;
245
	// if (c) rdColorMacroArg = c;
246
	// else rdColorMacroArg=[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.98 alpha:1.0];
246
	// else rdColorMacroArg=[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.98 alpha:1.0];
247
	// [rdColorMacroArg retain];
247
	// [rdColorMacroArg retain];
248
	// 
248
	// 
249
	// c=[Preferences unarchivedObjectForKey:macroGenRdSyntaxColorKey withDefault:nil];
249
	// c=[Preferences unarchivedObjectForKey:macroGenRdSyntaxColorKey withDefault:nil];
250
	// if (c) rdColorMacroGen = c;
250
	// if (c) rdColorMacroGen = c;
251
	// else rdColorMacroGen=[NSColor colorWithDeviceRed:0.4 green:0.78 blue:0.98 alpha:1.0];
251
	// else rdColorMacroGen=[NSColor colorWithDeviceRed:0.4 green:0.78 blue:0.98 alpha:1.0];
252
	// [rdColorMacroGen retain]; 
252
	// [rdColorMacroGen retain]; 
253
	// 
253
	// 
254
	// c=[Preferences unarchivedObjectForKey:directiveRdSyntaxColorKey withDefault:nil];
254
	// c=[Preferences unarchivedObjectForKey:directiveRdSyntaxColorKey withDefault:nil];
255
	// if (c) rdColorDirective = c;
255
	// if (c) rdColorDirective = c;
256
	// else rdColorDirective=[NSColor colorWithDeviceRed:0.0 green:0.785 blue:0.0 alpha:1.0];
256
	// else rdColorDirective=[NSColor colorWithDeviceRed:0.0 green:0.785 blue:0.0 alpha:1.0];
257
	// [rdColorDirective retain]; 
257
	// [rdColorDirective retain]; 
258
 
258
 
259
	// c=[Preferences unarchivedObjectForKey:commentRdSyntaxColorKey withDefault:nil];
259
	// c=[Preferences unarchivedObjectForKey:commentRdSyntaxColorKey withDefault:nil];
260
	// if (c) rdColorComment = c;
260
	// if (c) rdColorComment = c;
261
	// else rdColorComment=[NSColor colorWithDeviceRed:0.1 green:0.55 blue:0.05 alpha:1.0];
261
	// else rdColorComment=[NSColor colorWithDeviceRed:0.1 green:0.55 blue:0.05 alpha:1.0];
262
	// [rdColorComment retain];
262
	// [rdColorComment retain];
263
 
263
 
264
	// c=[Preferences unarchivedObjectForKey:normalRdSyntaxColorKey withDefault:nil];
264
	// c=[Preferences unarchivedObjectForKey:normalRdSyntaxColorKey withDefault:nil];
265
	// if (c) rdColorNormal = c;
265
	// if (c) rdColorNormal = c;
266
	// else rdColorNormal=[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:1.0];
266
	// else rdColorNormal=[NSColor colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:1.0];
267
	// [rdColorNormal retain]; 
267
	// [rdColorNormal retain]; 
268
 
268
 
269
 
269
 
270
	c=[Preferences unarchivedObjectForKey:editorBackgroundColorKey withDefault:nil];
270
	c=[Preferences unarchivedObjectForKey:editorBackgroundColorKey withDefault:nil];
271
	if (c) shColorBackground = c;
271
	if (c) shColorBackground = c;
272
	else shColorBackground=[NSColor colorWithDeviceRed:1.0 green:1.0 blue:1.0 alpha:1.0];
272
	else shColorBackground=[NSColor colorWithDeviceRed:1.0 green:1.0 blue:1.0 alpha:1.0];
273
	[shColorBackground retain]; 
273
	[shColorBackground retain]; 
274
 
274
 
275
	c=[Preferences unarchivedObjectForKey:editorCurrentLineBackgroundColorKey withDefault:nil];
275
	c=[Preferences unarchivedObjectForKey:editorCurrentLineBackgroundColorKey withDefault:nil];
276
	if (c) shColorCurrentLine = c;
276
	if (c) shColorCurrentLine = c;
277
	else shColorCurrentLine=[NSColor colorWithDeviceRed:0.9 green:0.9 blue:0.9 alpha:0.8];
277
	else shColorCurrentLine=[NSColor colorWithDeviceRed:0.9 green:0.9 blue:0.9 alpha:0.8];
278
	[shColorCurrentLine retain]; 
278
	[shColorCurrentLine retain]; 
279
 
279
 
280
	c=[Preferences unarchivedObjectForKey:editorCursorColorKey withDefault:nil];
280
	c=[Preferences unarchivedObjectForKey:editorCursorColorKey withDefault:nil];
281
	if (c) shColorCursor = c;
281
	if (c) shColorCursor = c;
282
	else shColorCursor=[NSColor blackColor];
282
	else shColorCursor=[NSColor blackColor];
283
	[shColorCursor retain]; 
283
	[shColorCursor retain]; 
284
	[self setInsertionPointColor:shColorCursor];
284
	[self setInsertionPointColor:shColorCursor];
285
 
285
 
286
	// Register observers for the when editor background colors preference changes
286
	// Register observers for the when editor background colors preference changes
287
	[prefs addObserver:self forKeyPath:normalSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
287
	[prefs addObserver:self forKeyPath:normalSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
288
	[prefs addObserver:self forKeyPath:stringSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
288
	[prefs addObserver:self forKeyPath:stringSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
289
	[prefs addObserver:self forKeyPath:numberSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
289
	[prefs addObserver:self forKeyPath:numberSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
290
	[prefs addObserver:self forKeyPath:keywordSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
290
	[prefs addObserver:self forKeyPath:keywordSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
291
	[prefs addObserver:self forKeyPath:commentSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
291
	[prefs addObserver:self forKeyPath:commentSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
292
	// [prefs addObserver:self forKeyPath:normalRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
292
	// [prefs addObserver:self forKeyPath:normalRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
293
	// [prefs addObserver:self forKeyPath:commentRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
293
	// [prefs addObserver:self forKeyPath:commentRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
294
	// [prefs addObserver:self forKeyPath:sectionRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
294
	// [prefs addObserver:self forKeyPath:sectionRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
295
	// [prefs addObserver:self forKeyPath:macroArgRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
295
	// [prefs addObserver:self forKeyPath:macroArgRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
296
	// [prefs addObserver:self forKeyPath:macroGenRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
296
	// [prefs addObserver:self forKeyPath:macroGenRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
297
	// [prefs addObserver:self forKeyPath:directiveRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
297
	// [prefs addObserver:self forKeyPath:directiveRdSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
298
	[prefs addObserver:self forKeyPath:editorBackgroundColorKey options:NSKeyValueObservingOptionNew context:NULL];
298
	[prefs addObserver:self forKeyPath:editorBackgroundColorKey options:NSKeyValueObservingOptionNew context:NULL];
299
	[prefs addObserver:self forKeyPath:editorCurrentLineBackgroundColorKey options:NSKeyValueObservingOptionNew context:NULL];
299
	[prefs addObserver:self forKeyPath:editorCurrentLineBackgroundColorKey options:NSKeyValueObservingOptionNew context:NULL];
300
	[prefs addObserver:self forKeyPath:identifierSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
300
	[prefs addObserver:self forKeyPath:identifierSyntaxColorKey options:NSKeyValueObservingOptionNew context:NULL];
301
	[prefs addObserver:self forKeyPath:editorCursorColorKey options:NSKeyValueObservingOptionNew context:NULL];
301
	[prefs addObserver:self forKeyPath:editorCursorColorKey options:NSKeyValueObservingOptionNew context:NULL];
302
	[prefs addObserver:self forKeyPath:showSyntaxColoringKey options:NSKeyValueObservingOptionNew context:NULL];
302
	[prefs addObserver:self forKeyPath:showSyntaxColoringKey options:NSKeyValueObservingOptionNew context:NULL];
303
	[prefs addObserver:self forKeyPath:prefShowArgsHints options:NSKeyValueObservingOptionNew context:NULL];
303
	[prefs addObserver:self forKeyPath:prefShowArgsHints options:NSKeyValueObservingOptionNew context:NULL];
304
	[prefs addObserver:self forKeyPath:enableLineWrappingKey options:NSKeyValueObservingOptionNew context:NULL];
304
	[prefs addObserver:self forKeyPath:enableLineWrappingKey options:NSKeyValueObservingOptionNew context:NULL];
305
	[prefs addObserver:self forKeyPath:RScriptEditorDefaultFont options:NSKeyValueObservingOptionNew context:NULL];
305
	[prefs addObserver:self forKeyPath:RScriptEditorDefaultFont options:NSKeyValueObservingOptionNew context:NULL];
306
	[prefs addObserver:self forKeyPath:HighlightIntervalKey options:NSKeyValueObservingOptionNew context:NULL];
306
	[prefs addObserver:self forKeyPath:HighlightIntervalKey options:NSKeyValueObservingOptionNew context:NULL];
307
	[prefs addObserver:self forKeyPath:highlightCurrentLine options:NSKeyValueObservingOptionNew context:NULL];
307
	[prefs addObserver:self forKeyPath:highlightCurrentLine options:NSKeyValueObservingOptionNew context:NULL];
308
	[prefs addObserver:self forKeyPath:showLineNumbersKey options:NSKeyValueObservingOptionNew context:NULL];
308
	[prefs addObserver:self forKeyPath:showLineNumbersKey options:NSKeyValueObservingOptionNew context:NULL];
309
	[prefs addObserver:self forKeyPath:editorSelectionBackgroundColorKey options:NSKeyValueObservingOptionNew context:NULL];
309
	[prefs addObserver:self forKeyPath:editorSelectionBackgroundColorKey options:NSKeyValueObservingOptionNew context:NULL];
310
 
310
 
311
	if(syntaxHighlightingEnabled) {
311
	if(syntaxHighlightingEnabled) {
312
		[self setTextColor:shColorNormal];
312
		[self setTextColor:shColorNormal];
313
		[self setInsertionPointColor:shColorCursor];
313
		[self setInsertionPointColor:shColorCursor];
314
	} else {
314
	} else {
315
		[self setTextColor:shColorNormal];
315
		[self setTextColor:shColorNormal];
316
		[self setInsertionPointColor:shColorCursor];
316
		[self setInsertionPointColor:shColorCursor];
317
	}
317
	}
318
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
318
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
319
	[[self layoutManager] setAllowsNonContiguousLayout:YES];
319
	[[self layoutManager] setAllowsNonContiguousLayout:YES];
320
#endif
320
#endif
321
 
321
 
322
	// add NSViewBoundsDidChangeNotification to scrollView
322
	// add NSViewBoundsDidChangeNotification to scrollView
323
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(boundsDidChangeNotification:) name:NSViewBoundsDidChangeNotification object:[scrollView contentView]];
323
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(boundsDidChangeNotification:) name:NSViewBoundsDidChangeNotification object:[scrollView contentView]];
324
 
324
 
325
}
325
}
326
 
326
 
327
- (void)dealloc {
327
- (void)dealloc {
328
	SLog(@"RScriptEditorTextView: dealloc <%@>", self);
328
	SLog(@"RScriptEditorTextView: dealloc <%@>", self);
329
 
329
 
330
	[theTextStorage release];
330
	[theTextStorage release];
331
 
331
 
332
	if(scrollView) [scrollView release];
332
	if(scrollView) [scrollView release];
333
	if(editorToolbar) [editorToolbar release];
333
	if(editorToolbar) [editorToolbar release];
334
 
334
 
335
	if(highlightColorAttr) [highlightColorAttr release];
335
	if(highlightColorAttr) [highlightColorAttr release];
336
 
336
 
337
	if(shColorNormal) [shColorNormal release];
337
	if(shColorNormal) [shColorNormal release];
338
	if(shColorString) [shColorString release];
338
	if(shColorString) [shColorString release];
339
	if(shColorNumber) [shColorNumber release];
339
	if(shColorNumber) [shColorNumber release];
340
	if(shColorKeyword) [shColorKeyword release];
340
	if(shColorKeyword) [shColorKeyword release];
341
	if(shColorComment) [shColorComment release];
341
	if(shColorComment) [shColorComment release];
342
	if(shColorIdentifier) [shColorIdentifier release];
342
	if(shColorIdentifier) [shColorIdentifier release];
343
	if(shColorBackground) [shColorBackground release];
343
	if(shColorBackground) [shColorBackground release];
344
	if(shColorCurrentLine) [shColorCurrentLine release];
344
	if(shColorCurrentLine) [shColorCurrentLine release];
345
	if(shColorCursor) [shColorCursor release];
345
	if(shColorCursor) [shColorCursor release];
346
 
346
 
347
	// if(rdColorNormal) [rdColorNormal release];
347
	// if(rdColorNormal) [rdColorNormal release];
348
	// if(rdColorComment) [rdColorComment release];
348
	// if(rdColorComment) [rdColorComment release];
349
	// if(rdColorSection) [rdColorSection release];
349
	// if(rdColorSection) [rdColorSection release];
350
	// if(rdColorMacroArg) [rdColorMacroArg release];
350
	// if(rdColorMacroArg) [rdColorMacroArg release];
351
	// if(rdColorMacroGen) [rdColorMacroGen release];
351
	// if(rdColorMacroGen) [rdColorMacroGen release];
352
	// if(rdColorDirective) [rdColorDirective release];
352
	// if(rdColorDirective) [rdColorDirective release];
353
 
353
 
354
	[[NSNotificationCenter defaultCenter] removeObserver:self];
354
	[[NSNotificationCenter defaultCenter] removeObserver:self];
355
	[[Preferences sharedPreferences] removeDependent:self];
355
	[[Preferences sharedPreferences] removeDependent:self];
356
	if(prefs) [prefs release];
356
	if(prefs) [prefs release];
357
 
357
 
358
	[super dealloc];
358
	[super dealloc];
359
 
359
 
360
}
360
}
361
 
361
 
362
- (id)scrollView
362
- (id)scrollView
363
{
363
{
364
	return scrollView;
364
	return scrollView;
365
}
365
}
366
 
366
 
367
- (void)setNonSyntaxHighlighting
367
- (void)setNonSyntaxHighlighting
368
{
368
{
369
	[theTextStorage removeAttribute:NSForegroundColorAttributeName range:NSMakeRange(0, [[theTextStorage string] length])];
369
	[theTextStorage removeAttribute:NSForegroundColorAttributeName range:NSMakeRange(0, [[theTextStorage string] length])];
370
	[theTextStorage removeAttribute:NSBackgroundColorAttributeName range:NSMakeRange(0, [[theTextStorage string] length])];
370
	[theTextStorage removeAttribute:NSBackgroundColorAttributeName range:NSMakeRange(0, [[theTextStorage string] length])];
371
	[self setTextColor:shColorNormal];
371
	[self setTextColor:shColorNormal];
372
	[self setInsertionPointColor:shColorCursor];
372
	[self setInsertionPointColor:shColorCursor];
373
	[self setNeedsDisplayInRect:[self visibleRect]];
373
	[self setNeedsDisplayInRect:[self visibleRect]];
374
}
374
}
375
 
375
 
376
/**
376
/**
377
 * This method is called as part of Key Value Observing which is used to watch for prefernce changes which effect the interface.
377
 * This method is called as part of Key Value Observing which is used to watch for prefernce changes which effect the interface.
378
 */
378
 */
379
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
379
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
380
{
380
{
381
 
381
 
382
	if ([keyPath isEqualToString:normalSyntaxColorKey]) {
382
	if ([keyPath isEqualToString:normalSyntaxColorKey]) {
383
		if(shColorNormal) [shColorNormal release];
383
		if(shColorNormal) [shColorNormal release];
384
		shColorNormal = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
384
		shColorNormal = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
385
		if([self isEditable])
385
		if([self isEditable])
386
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
386
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
387
	} else if ([keyPath isEqualToString:stringSyntaxColorKey]) {
387
	} else if ([keyPath isEqualToString:stringSyntaxColorKey]) {
388
		if(shColorString) [shColorString release];
388
		if(shColorString) [shColorString release];
389
		shColorString = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
389
		shColorString = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
390
		if([self isEditable])
390
		if([self isEditable])
391
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
391
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
392
	} else if ([keyPath isEqualToString:numberSyntaxColorKey]) {
392
	} else if ([keyPath isEqualToString:numberSyntaxColorKey]) {
393
		if(shColorNumber) [shColorNumber release];
393
		if(shColorNumber) [shColorNumber release];
394
		shColorNumber = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
394
		shColorNumber = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
395
		if([self isEditable])
395
		if([self isEditable])
396
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
396
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
397
	} else if ([keyPath isEqualToString:keywordSyntaxColorKey]) {
397
	} else if ([keyPath isEqualToString:keywordSyntaxColorKey]) {
398
		if(shColorKeyword) [shColorKeyword release];
398
		if(shColorKeyword) [shColorKeyword release];
399
		shColorKeyword = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
399
		shColorKeyword = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
400
		if([self isEditable])
400
		if([self isEditable])
401
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
401
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
402
	} else if ([keyPath isEqualToString:commentSyntaxColorKey]) {
402
	} else if ([keyPath isEqualToString:commentSyntaxColorKey]) {
403
		if(shColorComment) [shColorComment release];
403
		if(shColorComment) [shColorComment release];
404
		shColorComment = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
404
		shColorComment = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
405
		if([self isEditable])
405
		if([self isEditable])
406
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
406
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
407
	} else if ([keyPath isEqualToString:identifierSyntaxColorKey]) {
407
	} else if ([keyPath isEqualToString:identifierSyntaxColorKey]) {
408
		if(shColorIdentifier) [shColorIdentifier release];
408
		if(shColorIdentifier) [shColorIdentifier release];
409
		shColorIdentifier = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
409
		shColorIdentifier = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
410
		if([self isEditable])
410
		if([self isEditable])
411
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
411
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
412
	// } else if ([keyPath isEqualToString:sectionRdSyntaxColorKey]) {
412
	// } else if ([keyPath isEqualToString:sectionRdSyntaxColorKey]) {
413
	// 	if(rdColorSection) [rdColorSection release];
413
	// 	if(rdColorSection) [rdColorSection release];
414
	// 	rdColorSection = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
414
	// 	rdColorSection = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
415
	// 	if([self isEditable])
415
	// 	if([self isEditable])
416
	// 		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
416
	// 		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
417
	// } else if ([keyPath isEqualToString:macroArgRdSyntaxColorKey]) {
417
	// } else if ([keyPath isEqualToString:macroArgRdSyntaxColorKey]) {
418
	// 	if(rdColorMacroArg) [rdColorMacroArg release];
418
	// 	if(rdColorMacroArg) [rdColorMacroArg release];
419
	// 	rdColorMacroArg = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
419
	// 	rdColorMacroArg = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
420
	// 	if([self isEditable])
420
	// 	if([self isEditable])
421
	// 		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
421
	// 		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
422
	// } else if ([keyPath isEqualToString:macroGenRdSyntaxColorKey]) {
422
	// } else if ([keyPath isEqualToString:macroGenRdSyntaxColorKey]) {
423
	// 	if(rdColorMacroGen) [rdColorMacroGen release];
423
	// 	if(rdColorMacroGen) [rdColorMacroGen release];
424
	// 	rdColorMacroGen = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
424
	// 	rdColorMacroGen = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
425
	// 	if([self isEditable])
425
	// 	if([self isEditable])
426
	// 		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
426
	// 		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
427
	// } else if ([keyPath isEqualToString:directiveRdSyntaxColorKey]) {
427
	// } else if ([keyPath isEqualToString:directiveRdSyntaxColorKey]) {
428
	// 	if(rdColorDirective) [rdColorDirective release];
428
	// 	if(rdColorDirective) [rdColorDirective release];
429
	// 	rdColorDirective = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
429
	// 	rdColorDirective = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
430
	// 	if([self isEditable])
430
	// 	if([self isEditable])
431
	// 		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
431
	// 		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
432
	} else if ([keyPath isEqualToString:editorCursorColorKey]) {
432
	} else if ([keyPath isEqualToString:editorCursorColorKey]) {
433
		if(shColorCursor) [shColorCursor release];
433
		if(shColorCursor) [shColorCursor release];
434
		shColorCursor = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
434
		shColorCursor = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
435
		[self setInsertionPointColor:shColorCursor];
435
		[self setInsertionPointColor:shColorCursor];
436
		[self setNeedsDisplayInRect:[self visibleRect]];
436
		[self setNeedsDisplayInRect:[self visibleRect]];
437
	} else if ([keyPath isEqualToString:identifierSyntaxColorKey]) {
437
	} else if ([keyPath isEqualToString:identifierSyntaxColorKey]) {
438
		if(shColorIdentifier) [shColorIdentifier release];
438
		if(shColorIdentifier) [shColorIdentifier release];
439
		shColorIdentifier = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
439
		shColorIdentifier = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
440
		if([self isEditable])
440
		if([self isEditable])
441
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
441
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.1];
442
	} else if ([keyPath isEqualToString:editorBackgroundColorKey]) {
442
	} else if ([keyPath isEqualToString:editorBackgroundColorKey]) {
443
		if(shColorBackground) [shColorBackground release];
443
		if(shColorBackground) [shColorBackground release];
444
		shColorBackground = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
444
		shColorBackground = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
445
		[self setNeedsDisplayInRect:[self visibleRect]];
445
		[self setNeedsDisplayInRect:[self visibleRect]];
446
	} else if ([keyPath isEqualToString:editorCurrentLineBackgroundColorKey]) {
446
	} else if ([keyPath isEqualToString:editorCurrentLineBackgroundColorKey]) {
447
		if(shColorCurrentLine) [shColorCurrentLine release];
447
		if(shColorCurrentLine) [shColorCurrentLine release];
448
		shColorCurrentLine = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
448
		shColorCurrentLine = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
449
		[self setNeedsDisplayInRect:[self visibleRect]];
449
		[self setNeedsDisplayInRect:[self visibleRect]];
450
	} else if ([keyPath isEqualToString:editorSelectionBackgroundColorKey]) {
450
	} else if ([keyPath isEqualToString:editorSelectionBackgroundColorKey]) {
451
		NSColor *c = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
451
		NSColor *c = [[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]] retain];
452
		NSMutableDictionary *attr = [NSMutableDictionary dictionary];
452
		NSMutableDictionary *attr = [NSMutableDictionary dictionary];
453
		[attr setDictionary:[self selectedTextAttributes]];
453
		[attr setDictionary:[self selectedTextAttributes]];
454
		[attr setObject:c forKey:NSBackgroundColorAttributeName];
454
		[attr setObject:c forKey:NSBackgroundColorAttributeName];
455
		[self setSelectedTextAttributes:attr];
455
		[self setSelectedTextAttributes:attr];
456
		[self setNeedsDisplayInRect:[self visibleRect]];
456
		[self setNeedsDisplayInRect:[self visibleRect]];
457
 
457
 
458
	} else if ([keyPath isEqualToString:showSyntaxColoringKey]) {
458
	} else if ([keyPath isEqualToString:showSyntaxColoringKey]) {
459
		syntaxHighlightingEnabled = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
459
		syntaxHighlightingEnabled = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
460
		if(syntaxHighlightingEnabled) {
460
		if(syntaxHighlightingEnabled) {
461
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.05f];
461
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.05f];
462
		} else {
462
		} else {
463
			[self performSelector:@selector(setNonSyntaxHighlighting) withObject:nil afterDelay:0.05f];
463
			[self performSelector:@selector(setNonSyntaxHighlighting) withObject:nil afterDelay:0.05f];
464
		}
464
		}
465
	} else if ([keyPath isEqualToString:enableLineWrappingKey]) {
465
	} else if ([keyPath isEqualToString:enableLineWrappingKey]) {
466
		[self updateLineWrappingMode];
466
		[self updateLineWrappingMode];
467
		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.05f];
467
		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.05f];
468
		[self setNeedsDisplay:YES];
468
		[self setNeedsDisplay:YES];
469
 
469
 
470
	} else if ([keyPath isEqualToString:showLineNumbersKey]) {
470
	} else if ([keyPath isEqualToString:showLineNumbersKey]) {
471
		lineNumberingEnabled = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
471
		lineNumberingEnabled = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
472
		if(lineNumberingEnabled) {
472
		if(lineNumberingEnabled) {
473
			NoodleLineNumberView *theRulerView = [[NoodleLineNumberView alloc] initWithScrollView:scrollView];
473
			NoodleLineNumberView *theRulerView = [[NoodleLineNumberView alloc] initWithScrollView:scrollView];
474
			[scrollView setVerticalRulerView:theRulerView];
474
			[scrollView setVerticalRulerView:theRulerView];
475
			[scrollView setHasHorizontalRuler:NO];
475
			[scrollView setHasHorizontalRuler:NO];
476
			[scrollView setHasVerticalRuler:YES];
476
			[scrollView setHasVerticalRuler:YES];
477
			[scrollView setRulersVisible:YES];
477
			[scrollView setRulersVisible:YES];
478
			[theRulerView release];
478
			[theRulerView release];
479
			[(NoodleLineNumberView*)[[self enclosingScrollView] verticalRulerView] setLineWrappingMode:[Preferences flagForKey:enableLineWrappingKey withDefault: YES]];
479
			[(NoodleLineNumberView*)[[self enclosingScrollView] verticalRulerView] setLineWrappingMode:[Preferences flagForKey:enableLineWrappingKey withDefault: YES]];
480
		} else {
480
		} else {
481
			[scrollView setHasHorizontalRuler:NO];
481
			[scrollView setHasHorizontalRuler:NO];
482
			[scrollView setHasVerticalRuler:NO];
482
			[scrollView setHasVerticalRuler:NO];
483
			[scrollView setRulersVisible:NO];
483
			[scrollView setRulersVisible:NO];
484
		}
484
		}
485
		[self setNeedsDisplay:YES];
485
		[self setNeedsDisplay:YES];
486
 
486
 
487
	} else if ([keyPath isEqualToString:prefShowArgsHints]) {
487
	} else if ([keyPath isEqualToString:prefShowArgsHints]) {
488
		argsHints = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
488
		argsHints = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
489
		if(!argsHints) {
489
		if(!argsHints) {
490
			[selfDelegate setStatusLineText:@""];
490
			[selfDelegate setStatusLineText:@""];
491
		} else {
491
		} else {
492
			[self currentFunctionHint];
492
			[self currentFunctionHint];
493
		}
493
		}
494
 
494
 
495
	} else if ([keyPath isEqualToString:highlightCurrentLine]) {
495
	} else if ([keyPath isEqualToString:highlightCurrentLine]) {
496
		[self setNeedsDisplayInRect:[self visibleRect]];
496
		[self setNeedsDisplayInRect:[self visibleRect]];
497
 
497
 
498
	} else if ([keyPath isEqualToString:RScriptEditorDefaultFont] && ![[[[self window] windowController] document] isRTF] && ![self selectedRange].length) {
498
	} else if ([keyPath isEqualToString:RScriptEditorDefaultFont] && ![[[[self window] windowController] document] isRTF] && ![self selectedRange].length) {
499
			[self setFont:[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]]];
499
			[self setFont:[NSUnarchiver unarchiveObjectWithData:[change objectForKey:NSKeyValueChangeNewKey]]];
500
			[self setNeedsDisplayInRect:[self visibleRect]];
500
			[self setNeedsDisplayInRect:[self visibleRect]];
501
	
501
	
502
		} else if ([keyPath isEqualToString:HighlightIntervalKey]) {
502
		} else if ([keyPath isEqualToString:HighlightIntervalKey]) {
503
		braceHighlightInterval = [Preferences floatForKey:HighlightIntervalKey withDefault:0.3f];
503
		braceHighlightInterval = [Preferences floatForKey:HighlightIntervalKey withDefault:0.3f];
504
	}
504
	}
505
}
505
}
506
 
506
 
507
- (void)updateLineWrappingMode
507
- (void)updateLineWrappingMode
508
{
508
{
509
 
509
 
510
	NSSize layoutSize;
510
	NSSize layoutSize;
511
	
511
	
512
	lineWrappingEnabled = [Preferences flagForKey:enableLineWrappingKey withDefault: YES];
512
	lineWrappingEnabled = [Preferences flagForKey:enableLineWrappingKey withDefault: YES];
513
 
513
 
514
	[self setHorizontallyResizable:YES];
514
	[self setHorizontallyResizable:YES];
515
	if (!lineWrappingEnabled) {
515
	if (!lineWrappingEnabled) {
516
		NSRange curRange = [self selectedRange];
516
		NSRange curRange = [self selectedRange];
517
		layoutSize = NSMakeSize(10e6,10e6);
517
		layoutSize = NSMakeSize(10e6,10e6);
518
		[scrollView setHasHorizontalScroller:YES];
518
		[scrollView setHasHorizontalScroller:YES];
519
		[self setMaxSize:layoutSize];
519
		[self setMaxSize:layoutSize];
520
		[[self textContainer] setContainerSize:layoutSize];
520
		[[self textContainer] setContainerSize:layoutSize];
521
		[[self textContainer] setWidthTracksTextView:NO];
521
		[[self textContainer] setWidthTracksTextView:NO];
522
		[self scrollRangeToVisible:NSMakeRange(curRange.location, 0)];
522
		[self scrollRangeToVisible:NSMakeRange(curRange.location, 0)];
523
	} else {
523
	} else {
524
		[scrollView setHasHorizontalScroller:NO];
524
		[scrollView setHasHorizontalScroller:NO];
525
		layoutSize = [self maxSize];
525
		layoutSize = [self maxSize];
526
		[self setMaxSize:layoutSize];
526
		[self setMaxSize:layoutSize];
527
		[[self textContainer] setContainerSize:layoutSize];
527
		[[self textContainer] setContainerSize:layoutSize];
528
		[[self textContainer] setWidthTracksTextView:YES];
528
		[[self textContainer] setWidthTracksTextView:YES];
529
		// Enforce view to be re-layouted correctly
529
		// Enforce view to be re-layouted correctly
530
		// by re-inserting the the current text buffer
530
		// by re-inserting the the current text buffer
531
		[[self undoManager] disableUndoRegistration];
531
		[[self undoManager] disableUndoRegistration];
532
		NSRange curRange = [self selectedRange];
532
		NSRange curRange = [self selectedRange];
533
		NSString *t = [[NSString alloc] initWithString:[self string]];
533
		NSString *t = [[NSString alloc] initWithString:[self string]];
534
		[self selectAll:nil];
534
		[self selectAll:nil];
535
		[self insertText:@""];
535
		[self insertText:@""];
536
		usleep(1000);
536
		usleep(1000);
537
		[self insertText:t];
537
		[self insertText:t];
538
		[t release];
538
		[t release];
539
		[self setSelectedRange:curRange];
539
		[self setSelectedRange:curRange];
540
		[self scrollRangeToVisible:NSMakeRange(curRange.location, 0)];
540
		[self scrollRangeToVisible:NSMakeRange(curRange.location, 0)];
541
		[[self undoManager] enableUndoRegistration];
541
		[[self undoManager] enableUndoRegistration];
542
	}
542
	}
543
	[[self textContainer] setHeightTracksTextView:NO];
543
	[[self textContainer] setHeightTracksTextView:NO];
544
 
544
 
545
}
545
}
546
 
546
 
547
- (void)drawRect:(NSRect)rect
547
- (void)drawRect:(NSRect)rect
548
{
548
{
549
	// Draw background only for screen display but not while printing
549
	// Draw background only for screen display but not while printing
550
	if([NSGraphicsContext currentContextDrawingToScreen]) {
550
	if([NSGraphicsContext currentContextDrawingToScreen]) {
551
 
551
 
552
		// Draw textview's background
552
		// Draw textview's background
553
		[shColorBackground setFill];
553
		[shColorBackground setFill];
554
		NSRectFill(rect);
554
		NSRectFill(rect);
555
 
555
 
556
		// Highlightes the current line if set in the Pref
556
		// Highlightes the current line if set in the Pref
557
		// and if nothing is selected in the text view
557
		// and if nothing is selected in the text view
558
		if ([prefs boolForKey:highlightCurrentLine] && ![self selectedRange].length && ![self isSnippetMode]) {
558
		if ([prefs boolForKey:highlightCurrentLine] && ![self selectedRange].length && ![self isSnippetMode]) {
559
			NSUInteger rectCount;
559
			NSUInteger rectCount;
560
			NSRange curLineRange = [[self string] lineRangeForRange:[self selectedRange]];
560
			NSRange curLineRange = [[self string] lineRangeForRange:[self selectedRange]];
561
			// [theTextStorage ensureAttributesAreFixedInRange:curLineRange];
561
			// [theTextStorage ensureAttributesAreFixedInRange:curLineRange];
562
			NSRectArray queryRects = [[self layoutManager] rectArrayForCharacterRange: curLineRange
562
			NSRectArray queryRects = [[self layoutManager] rectArrayForCharacterRange: curLineRange
563
														 withinSelectedCharacterRange: curLineRange
563
														 withinSelectedCharacterRange: curLineRange
564
																	  inTextContainer: [self textContainer]
564
																	  inTextContainer: [self textContainer]
565
																			rectCount: &rectCount ];
565
																			rectCount: &rectCount ];
566
			[shColorCurrentLine setFill];
566
			[shColorCurrentLine setFill];
567
			NSRectFillListUsingOperation(queryRects, rectCount, NSCompositeSourceOver);
567
			NSRectFillListUsingOperation(queryRects, rectCount, NSCompositeSourceOver);
568
		}
568
		}
569
	}
569
	}
570
	[super drawRect:rect];
570
	[super drawRect:rect];
571
}
571
}
572
 
572
 
573
#pragma mark -
573
#pragma mark -
574
 
574
 
575
/**
575
/**
576
 *  Performs syntax highlighting, trigger undo behaviour
576
 *  Performs syntax highlighting, trigger undo behaviour
577
 */
577
 */
578
- (void)textStorageDidProcessEditing:(NSNotification *)notification
578
- (void)textStorageDidProcessEditing:(NSNotification *)notification
579
{
579
{
580
 
580
 
581
	// Make sure that the notification is from the correct textStorage object
581
	// Make sure that the notification is from the correct textStorage object
582
	if (theTextStorage != [notification object]) return;
582
	if (theTextStorage != [notification object]) return;
583
 
583
 
584
	NSInteger editedMask = [theTextStorage editedMask];
584
	NSInteger editedMask = [theTextStorage editedMask];
585
 
585
 
586
	SLog(@"RScriptEditorTextView: textStorageDidProcessEditing <%@> with mask %d", self, editedMask);
586
	SLog(@"RScriptEditorTextView: textStorageDidProcessEditing <%@> with mask %d", self, editedMask);
587
 
587
 
588
	// if the user really changed the text
588
	// if the user really changed the text
589
	if(editedMask != 1) {
589
	if(editedMask != 1) {
590
 
590
 
591
		// For larger text break a running syntax highlighting for user interaction
591
		// For larger text break a running syntax highlighting for user interaction
592
		// to make them more responsive (typing and scrolling)
592
		// to make them more responsive (typing and scrolling)
593
		// if([[theTextStorage string] length] > 120000) {
593
		// if([[theTextStorage string] length] > 120000) {
594
		// 	breakSyntaxHighlighting = 1;
594
		// 	breakSyntaxHighlighting = 1;
595
		// }
595
		// }
596
 
596
 
597
		[self checkSnippets];
597
		[self checkSnippets];
598
 
598
 
599
		breakSyntaxHighlighting = 1;
599
		breakSyntaxHighlighting = 1;
600
 
600
 
601
		// Cancel calling doSyntaxHighlighting
601
		// Cancel calling doSyntaxHighlighting
602
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
602
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
603
								selector:@selector(doSyntaxHighlighting) 
603
								selector:@selector(doSyntaxHighlighting) 
604
								object:nil];
604
								object:nil];
605
 
605
 
606
		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.05f];
606
		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.05f];
607
 
607
 
608
		// Cancel setting undo break point
608
		// Cancel setting undo break point
609
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
609
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
610
								selector:@selector(breakUndoCoalescing) 
610
								selector:@selector(breakUndoCoalescing) 
611
								object:nil];
611
								object:nil];
612
 
612
 
613
		// Improve undo behaviour, i.e. it depends how fast the user types
613
		// Improve undo behaviour, i.e. it depends how fast the user types
614
		[self performSelector:@selector(breakUndoCoalescing) withObject:nil afterDelay:0.8f];
614
		[self performSelector:@selector(breakUndoCoalescing) withObject:nil afterDelay:0.8f];
615
 
615
 
616
		[NSObject cancelPreviousPerformRequestsWithTarget:(RDocumentWinCtrl*)[self delegate] 
616
		[NSObject cancelPreviousPerformRequestsWithTarget:(RDocumentWinCtrl*)[self delegate] 
617
								selector:@selector(functionRescan) 
617
								selector:@selector(functionRescan) 
618
								object:nil];
618
								object:nil];
619
 
619
 
620
		// update function list to display the function in which the cursor is located
620
		// update function list to display the function in which the cursor is located
621
		[(RDocumentWinCtrl*)[self delegate] performSelector:@selector(functionRescan) withObject:nil afterDelay:0.3f];
621
		[(RDocumentWinCtrl*)[self delegate] performSelector:@selector(functionRescan) withObject:nil afterDelay:0.3f];
622
 
622
 
623
	}
623
	}
624
 
624
 
625
	deleteBackward = NO;
625
	deleteBackward = NO;
626
	startListeningToBoundChanges = YES;
626
	startListeningToBoundChanges = YES;
627
 
627
 
628
}
628
}
629
 
629
 
630
#pragma mark -
630
#pragma mark -
631
 
631
 
632
- (BOOL)lineNumberingEnabled
632
- (BOOL)lineNumberingEnabled
633
{
633
{
634
	return lineNumberingEnabled;
634
	return lineNumberingEnabled;
635
}
635
}
636
 
636
 
637
- (void)setDeleteBackward:(BOOL)delBack
637
- (void)setDeleteBackward:(BOOL)delBack
638
{
638
{
639
	deleteBackward = delBack;
639
	deleteBackward = delBack;
640
}
640
}
641
 
641
 
642
/**
642
/**
643
 * Sets Tab Stops width for better editing behaviour
643
 * Sets Tab Stops width for better editing behaviour
644
 */
644
 */
645
- (void)setTabStops
645
- (void)setTabStops
646
{
646
{
647
 
647
 
648
	SLog(@"RScriptEditorTextView: setTabStops <%@>", self);
648
	SLog(@"RScriptEditorTextView: setTabStops <%@>", self);
649
 
649
 
650
	NSFont *tvFont = [self font];
650
	NSFont *tvFont = [self font];
651
	int i;
651
	int i;
652
	NSTextTab *aTab;
652
	NSTextTab *aTab;
653
	NSMutableArray *myArrayOfTabs;
653
	NSMutableArray *myArrayOfTabs;
654
	NSMutableParagraphStyle *paragraphStyle;
654
	NSMutableParagraphStyle *paragraphStyle;
655
 
655
 
656
	BOOL oldEditableStatus = [self isEditable];
656
	BOOL oldEditableStatus = [self isEditable];
657
	[self setEditable:YES];
657
	[self setEditable:YES];
658
 
658
 
659
	int tabStopWidth = [Preferences integerForKey:RScriptEditorTabWidth withDefault:4];
659
	int tabStopWidth = [Preferences integerForKey:RScriptEditorTabWidth withDefault:4];
660
	if(tabStopWidth < 1) tabStopWidth = 1;
660
	if(tabStopWidth < 1) tabStopWidth = 1;
661
 
661
 
662
	float theTabWidth = [[NSString stringWithString:@" "] sizeWithAttributes:[NSDictionary dictionaryWithObject:tvFont forKey:NSFontAttributeName]].width;
662
	float theTabWidth = [[NSString stringWithString:@" "] sizeWithAttributes:[NSDictionary dictionaryWithObject:tvFont forKey:NSFontAttributeName]].width;
663
	theTabWidth = (float)tabStopWidth * theTabWidth;
663
	theTabWidth = (float)tabStopWidth * theTabWidth;
664
 
664
 
665
	int numberOfTabs = 256/tabStopWidth;
665
	int numberOfTabs = 256/tabStopWidth;
666
	myArrayOfTabs = [NSMutableArray arrayWithCapacity:numberOfTabs];
666
	myArrayOfTabs = [NSMutableArray arrayWithCapacity:numberOfTabs];
667
	aTab = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:theTabWidth];
667
	aTab = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:theTabWidth];
668
	[myArrayOfTabs addObject:aTab];
668
	[myArrayOfTabs addObject:aTab];
669
	[aTab release];
669
	[aTab release];
670
	for(i=1; i<numberOfTabs; i++) {
670
	for(i=1; i<numberOfTabs; i++) {
671
		aTab = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:theTabWidth + ((float)i * theTabWidth)];
671
		aTab = [[NSTextTab alloc] initWithType:NSLeftTabStopType location:theTabWidth + ((float)i * theTabWidth)];
672
		[myArrayOfTabs addObject:aTab];
672
		[myArrayOfTabs addObject:aTab];
673
		[aTab release];
673
		[aTab release];
674
	}
674
	}
675
	paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
675
	paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
676
	[paragraphStyle setTabStops:myArrayOfTabs];
676
	[paragraphStyle setTabStops:myArrayOfTabs];
677
 
677
 
678
	// Soft wrapped lines are indented slightly
678
	// Soft wrapped lines are indented slightly
679
	[paragraphStyle setHeadIndent:4.0];
679
	[paragraphStyle setHeadIndent:4.0];
680
 
680
 
681
	NSMutableDictionary *textAttributes = [[[NSMutableDictionary alloc] initWithCapacity:1] autorelease];
681
	NSMutableDictionary *textAttributes = [[[NSMutableDictionary alloc] initWithCapacity:1] autorelease];
682
	[textAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
682
	[textAttributes setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];
683
 
683
 
684
	NSRange range = NSMakeRange(0, [theTextStorage length]);
684
	NSRange range = NSMakeRange(0, [theTextStorage length]);
685
	if ([self shouldChangeTextInRange:range replacementString:nil]) {
685
	if ([self shouldChangeTextInRange:range replacementString:nil]) {
686
		[theTextStorage setAttributes:textAttributes range: range];
686
		[theTextStorage setAttributes:textAttributes range: range];
687
		[self didChangeText];
687
		[self didChangeText];
688
	}
688
	}
689
	[self setTypingAttributes:textAttributes];
689
	[self setTypingAttributes:textAttributes];
690
	[self setDefaultParagraphStyle:paragraphStyle];
690
	[self setDefaultParagraphStyle:paragraphStyle];
691
	[self setFont:tvFont];
691
	[self setFont:tvFont];
692
 
692
 
693
	[self setEditable:oldEditableStatus];
693
	[self setEditable:oldEditableStatus];
694
 
694
 
695
	[paragraphStyle release];
695
	[paragraphStyle release];
696
}
696
}
697
 
697
 
698
- (BOOL)isSyntaxHighlighting
698
- (BOOL)isSyntaxHighlighting
699
{
699
{
700
	return isSyntaxHighlighting;
700
	return isSyntaxHighlighting;
701
}
701
}
702
 
702
 
703
- (BOOL)breakSyntaxHighlighting
703
- (BOOL)breakSyntaxHighlighting
704
{
704
{
705
	return breakSyntaxHighlighting;
705
	return breakSyntaxHighlighting;
706
}
706
}
707
/**
707
/**
708
 * Syntax Highlighting.
708
 * Syntax Highlighting.
709
 *  
709
 *  
710
 * (The main bottleneck is the [NSTextStorage addAttribute:value:range:] method - the parsing itself is really fast!)
710
 * (The main bottleneck is the [NSTextStorage addAttribute:value:range:] method - the parsing itself is really fast!)
711
 * Some sample code from Andrew Choi ( http://members.shaw.ca/akochoi-old/blog/2003/11-09/index.html#3 ) has been reused.
711
 * Some sample code from Andrew Choi ( http://members.shaw.ca/akochoi-old/blog/2003/11-09/index.html#3 ) has been reused.
712
 */
712
 */
713
- (void)doSyntaxHighlighting
713
- (void)doSyntaxHighlighting
714
{
714
{
715
 
715
 
716
	if(!syntaxHighlightingEnabled)
716
	if(!syntaxHighlightingEnabled)
717
		breakSyntaxHighlighting = 0;
717
		breakSyntaxHighlighting = 0;
718
 
718
 
719
	if (!syntaxHighlightingEnabled || [selfDelegate plain]) return;
719
	if (!syntaxHighlightingEnabled || [selfDelegate plain]) return;
720
 
720
 
721
	isSyntaxHighlighting = YES;
721
	isSyntaxHighlighting = YES;
722
 
722
 
723
	NSString *selfstr    = [theTextStorage string];
723
	NSString *selfstr    = [theTextStorage string];
724
	NSInteger strlength  = (NSInteger)[selfstr length];
724
	NSInteger strlength  = (NSInteger)[selfstr length];
725
 
725
 
726
	// do not highlight if text larger than 10MB
726
	// do not highlight if text larger than 10MB
727
	if(strlength > 10000000 || !strlength) {
727
	if(strlength > 10000000 || !strlength) {
728
		isSyntaxHighlighting = NO;
728
		isSyntaxHighlighting = NO;
729
		breakSyntaxHighlighting = 0;
729
		breakSyntaxHighlighting = 0;
730
		return;
730
		return;
731
	}
731
	}
732
 
732
 
733
	// == Do highlighting partly (max R_SYNTAX_HILITE_BIAS*2 around visibleRange
733
	// == Do highlighting partly (max R_SYNTAX_HILITE_BIAS*2 around visibleRange
734
	// by considering entire lines).
734
	// by considering entire lines).
735
 
735
 
736
	// Get the text range currently displayed in the view port
736
	// Get the text range currently displayed in the view port
737
	NSRect visibleRect = [self visibleRect];
737
	NSRect visibleRect = [self visibleRect];
738
	NSRange visibleRange = [[self layoutManager] glyphRangeForBoundingRectWithoutAdditionalLayout:visibleRect inTextContainer:[self textContainer]];
738
	NSRange visibleRange = [[self layoutManager] glyphRangeForBoundingRectWithoutAdditionalLayout:visibleRect inTextContainer:[self textContainer]];
739
 
739
 
740
	if(!visibleRange.length) {
740
	if(!visibleRange.length) {
741
		isSyntaxHighlighting = NO;
741
		isSyntaxHighlighting = NO;
742
		breakSyntaxHighlighting = 0;
742
		breakSyntaxHighlighting = 0;
743
		return;
743
		return;
744
	}
744
	}
745
 
745
 
746
	NSInteger start = visibleRange.location - R_SYNTAX_HILITE_BIAS;
746
	NSInteger start = visibleRange.location - R_SYNTAX_HILITE_BIAS;
747
	if (start > 0)
747
	if (start > 0)
748
		while(start > 0) {
748
		while(start > 0) {
749
			if(CFStringGetCharacterAtIndex((CFStringRef)selfstr, start)=='\n')
749
			if(CFStringGetCharacterAtIndex((CFStringRef)selfstr, start)=='\n')
750
				break;
750
				break;
751
			start--;
751
			start--;
752
		}
752
		}
753
	if(start < 0) start = 0;
753
	if(start < 0) start = 0;
754
	NSInteger end = NSMaxRange(visibleRange) + R_SYNTAX_HILITE_BIAS;
754
	NSInteger end = NSMaxRange(visibleRange) + R_SYNTAX_HILITE_BIAS;
755
	if (end > strlength) {
755
	if (end > strlength) {
756
		end = strlength;
756
		end = strlength;
757
	} else {
757
	} else {
758
		while(end < strlength) {
758
		while(end < strlength) {
759
			if(CFStringGetCharacterAtIndex((CFStringRef)selfstr, end)=='\n')
759
			if(CFStringGetCharacterAtIndex((CFStringRef)selfstr, end)=='\n')
760
				break;
760
				break;
761
			end++;
761
			end++;
762
		}
762
		}
763
	}
763
	}
764
 
764
 
765
	NSRange textRange = NSMakeRange(start, end-start);
765
	NSRange textRange = NSMakeRange(start, end-start);
766
 
766
 
767
	// only to be sure that nothing went wrongly
767
	// only to be sure that nothing went wrongly
768
	textRange = NSIntersectionRange(textRange, NSMakeRange(0, [theTextStorage length])); 
768
	textRange = NSIntersectionRange(textRange, NSMakeRange(0, [theTextStorage length])); 
769
 
769
 
770
	if (!textRange.length || textRange.length > 30000) {
770
	if (!textRange.length || textRange.length > 30000) {
771
		isSyntaxHighlighting = NO;
771
		isSyntaxHighlighting = NO;
772
		breakSyntaxHighlighting = 0;
772
		breakSyntaxHighlighting = 0;
773
		return;
773
		return;
774
	}
774
	}
775
 
775
 
776
	[theTextStorage beginEditing];
776
	[theTextStorage beginEditing];
777
 
777
 
778
	NSColor *tokenColor = nil;
778
	NSColor *tokenColor = nil;
779
 
779
 
780
	size_t token;
780
	size_t token;
781
	NSRange tokenRange;
781
	NSRange tokenRange;
782
 
782
 
783
	// initialise flex
783
	// initialise flex
784
	yyuoffset = textRange.location; yyuleng = 0;
784
	yyuoffset = textRange.location; yyuleng = 0;
785
	
785
	
786
	BOOL hasFoldedItems = [theTextStorage hasFoldedItems];
786
	BOOL hasFoldedItems = [theTextStorage hasFoldedItems];
787
 
787
 
788
	if([selfDelegate isRdDocument]) {
788
	if([selfDelegate isRdDocument]) {
789
 
789
 
790
			rd_switch_to_buffer(rd_scan_string(NSStringUTF8String([selfstr substringWithRange:textRange])));
790
			rd_switch_to_buffer(rd_scan_string(NSStringUTF8String([selfstr substringWithRange:textRange])));
791
 
791
 
792
			// now loop through all the tokens
792
			// now loop through all the tokens
793
			while ((token = rdlex())) {
793
			while ((token = rdlex())) {
794
				if(hasFoldedItems && (NSInteger)(_foldedImp)(theTextStorage, _foldedSel, yyuoffset) > -1) continue;
794
				if(hasFoldedItems && (NSInteger)(_foldedImp)(theTextStorage, _foldedSel, yyuoffset) > -1) continue;
795
				switch (token) {
795
				switch (token) {
796
					case RDPT_COMMENT:
796
					case RDPT_COMMENT:
797
					    tokenColor = shColorComment;
797
					    tokenColor = shColorComment;
798
					    break;
798
					    break;
799
					case RDPT_SECTION:
799
					case RDPT_SECTION:
800
					    tokenColor = shColorKeyword;
800
					    tokenColor = shColorKeyword;
801
					    break;
801
					    break;
802
					case RDPT_MACRO_ARG:
802
					case RDPT_MACRO_ARG:
803
					    tokenColor = shColorNumber;
803
					    tokenColor = shColorNumber;
804
					    break;
804
					    break;
805
					case RDPT_MACRO_GEN:
805
					case RDPT_MACRO_GEN:
806
					    tokenColor = shColorNumber;
806
					    tokenColor = shColorNumber;
807
					    break;
807
					    break;
808
					case RDPT_DIRECTIVE:
808
					case RDPT_DIRECTIVE:
809
					    tokenColor = shColorString;
809
					    tokenColor = shColorString;
810
					    break;
810
					    break;
811
					case RDPT_OTHER:
811
					case RDPT_OTHER:
812
					    tokenColor = shColorNormal;
812
					    tokenColor = shColorNormal;
813
					    break;
813
					    break;
814
					default:
814
					default:
815
					    tokenColor = shColorNormal;
815
					    tokenColor = shColorNormal;
816
				}
816
				}
817
 
817
 
818
				tokenRange = NSMakeRange(yyuoffset, yyuleng);
818
				tokenRange = NSMakeRange(yyuoffset, yyuleng);
819
 
819
 
820
				// make sure that tokenRange is valid (and therefore within textRange)
820
				// make sure that tokenRange is valid (and therefore within textRange)
821
				// otherwise a bug in the lex code could cause the the TextView to crash
821
				// otherwise a bug in the lex code could cause the the TextView to crash
822
				// NOTE Disabled for testing purposes for speed it up
822
				// NOTE Disabled for testing purposes for speed it up
823
				tokenRange = NSIntersectionRange(tokenRange, textRange);
823
				tokenRange = NSIntersectionRange(tokenRange, textRange);
824
				if (!tokenRange.length) continue;
824
				if (!tokenRange.length) continue;
825
 
825
 
826
				NSMutableAttributedStringAddAttributeValueRange(theTextStorage, NSForegroundColorAttributeName, tokenColor, tokenRange);
826
				NSMutableAttributedStringAddAttributeValueRange(theTextStorage, NSForegroundColorAttributeName, tokenColor, tokenRange);
827
 
827
 
828
				if(breakSyntaxHighlighting) {
828
				if(breakSyntaxHighlighting) {
829
 
829
 
830
					// Cancel calling doSyntaxHighlighting
830
					// Cancel calling doSyntaxHighlighting
831
					[NSObject cancelPreviousPerformRequestsWithTarget:self 
831
					[NSObject cancelPreviousPerformRequestsWithTarget:self 
832
											selector:@selector(doSyntaxHighlighting) 
832
											selector:@selector(doSyntaxHighlighting) 
833
											object:nil];
833
											object:nil];
834
 
834
 
835
					[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.08f];
835
					[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.08f];
836
 
836
 
837
					breakSyntaxHighlighting = 0;
837
					breakSyntaxHighlighting = 0;
838
					break;
838
					break;
839
 
839
 
840
				}
840
				}
841
 
841
 
842
			}
842
			}
843
 
843
 
844
	} else {
844
	} else {
845
 
845
 
846
		yy_switch_to_buffer(yy_scan_string(NSStringUTF8String([selfstr substringWithRange:textRange])));
846
		yy_switch_to_buffer(yy_scan_string(NSStringUTF8String([selfstr substringWithRange:textRange])));
847
 
847
 
848
		// now loop through all the tokens
848
		// now loop through all the tokens
849
		while ((token = yylex())) {
849
		while ((token = yylex())) {
850
			if(hasFoldedItems && (NSInteger)(_foldedImp)(theTextStorage, _foldedSel, yyuoffset) > -1) continue;
850
			if(hasFoldedItems && (NSInteger)(_foldedImp)(theTextStorage, _foldedSel, yyuoffset) > -1) continue;
851
			switch (token) {
851
			switch (token) {
852
				case RPT_SINGLE_QUOTED_TEXT:
852
				case RPT_SINGLE_QUOTED_TEXT:
853
				case RPT_DOUBLE_QUOTED_TEXT:
853
				case RPT_DOUBLE_QUOTED_TEXT:
854
				    tokenColor = shColorString;
854
				    tokenColor = shColorString;
855
				    break;
855
				    break;
856
				case RPT_RESERVED_WORD:
856
				case RPT_RESERVED_WORD:
857
				    tokenColor = shColorKeyword;
857
				    tokenColor = shColorKeyword;
858
				    break;
858
				    break;
859
				case RPT_NUMERIC:
859
				case RPT_NUMERIC:
860
					tokenColor = shColorNumber;
860
					tokenColor = shColorNumber;
861
					break;
861
					break;
862
				case RPT_BACKTICK_QUOTED_TEXT:
862
				case RPT_BACKTICK_QUOTED_TEXT:
863
				    tokenColor = shColorString;
863
				    tokenColor = shColorString;
864
				    break;
864
				    break;
865
				case RPT_COMMENT:
865
				case RPT_COMMENT:
866
				    tokenColor = shColorComment;
866
				    tokenColor = shColorComment;
867
				    break;
867
				    break;
868
				case RPT_VARIABLE:
868
				case RPT_VARIABLE:
869
				    tokenColor = shColorIdentifier;
869
				    tokenColor = shColorIdentifier;
870
				    break;
870
				    break;
871
				default:
871
				default:
872
				    tokenColor = shColorNormal;
872
				    tokenColor = shColorNormal;
873
			}
873
			}
874
 
874
 
875
			tokenRange = NSMakeRange(yyuoffset, yyuleng);
875
			tokenRange = NSMakeRange(yyuoffset, yyuleng);
876
 
876
 
877
			// make sure that tokenRange is valid (and therefore within textRange)
877
			// make sure that tokenRange is valid (and therefore within textRange)
878
			// otherwise a bug in the lex code could cause the the TextView to crash
878
			// otherwise a bug in the lex code could cause the the TextView to crash
879
			tokenRange = NSIntersectionRange(tokenRange, textRange);
879
			tokenRange = NSIntersectionRange(tokenRange, textRange);
880
			if (!tokenRange.length) continue;
880
			if (!tokenRange.length) continue;
881
 
881
 
882
			NSMutableAttributedStringAddAttributeValueRange(theTextStorage, NSForegroundColorAttributeName, tokenColor, tokenRange);
882
			NSMutableAttributedStringAddAttributeValueRange(theTextStorage, NSForegroundColorAttributeName, tokenColor, tokenRange);
883
 
883
 
884
			if(breakSyntaxHighlighting) {
884
			if(breakSyntaxHighlighting) {
885
 
885
 
886
				// Cancel calling doSyntaxHighlighting
886
				// Cancel calling doSyntaxHighlighting
887
				[NSObject cancelPreviousPerformRequestsWithTarget:self 
887
				[NSObject cancelPreviousPerformRequestsWithTarget:self 
888
										selector:@selector(doSyntaxHighlighting) 
888
										selector:@selector(doSyntaxHighlighting) 
889
										object:nil];
889
										object:nil];
890
				
890
				
891
				[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.08f];
891
				[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.08f];
892
 
892
 
893
				breakSyntaxHighlighting = 0;
893
				breakSyntaxHighlighting = 0;
894
				break;
894
				break;
895
 
895
 
896
			}
896
			}
897
 
897
 
898
		}
898
		}
899
 
899
 
900
	}
900
	}
901
 
901
 
902
	// set current textColor to the color of the caret's position - 1
902
	// set current textColor to the color of the caret's position - 1
903
	// to try to suppress writing in normalColor before syntax highlighting 
903
	// to try to suppress writing in normalColor before syntax highlighting 
904
	NSUInteger ix = [self selectedRange].location;
904
	NSUInteger ix = [self selectedRange].location;
905
	if(ix > 1) {
905
	if(ix > 1) {
906
		NSMutableDictionary *typeAttr = [NSMutableDictionary dictionary];
906
		NSMutableDictionary *typeAttr = [NSMutableDictionary dictionary];
907
		[typeAttr setDictionary:[self typingAttributes]];
907
		[typeAttr setDictionary:[self typingAttributes]];
908
		NSColor *c = [theTextStorage attribute:NSForegroundColorAttributeName atIndex:ix-1 effectiveRange:nil];
908
		NSColor *c = [theTextStorage attribute:NSForegroundColorAttributeName atIndex:ix-1 effectiveRange:nil];
909
		if(c) [typeAttr setObject:c forKey:NSForegroundColorAttributeName];
909
		if(c) [typeAttr setObject:c forKey:NSForegroundColorAttributeName];
910
		[self setTypingAttributes:typeAttr];
910
		[self setTypingAttributes:typeAttr];
911
	}
911
	}
912
 
912
 
913
	[theTextStorage endEditing];
913
	[theTextStorage endEditing];
914
 
914
 
915
	[self setNeedsDisplayInRect:visibleRect];
915
	[self setNeedsDisplayInRect:visibleRect];
916
 
916
 
917
	breakSyntaxHighlighting = 0;
917
	breakSyntaxHighlighting = 0;
918
 
918
 
919
	isSyntaxHighlighting = NO;
919
	isSyntaxHighlighting = NO;
920
 
920
 
921
}
921
}
922
 
922
 
923
-(void)resetHighlights
923
-(void)resetHighlights
924
{
924
{
925
 
925
 
926
	SLog(@"RScriptEditorTextView: resetHighlights with current highlite %d", currentHighlight);
926
	SLog(@"RScriptEditorTextView: resetHighlights with current highlite %d", currentHighlight);
927
 
927
 
928
	if (currentHighlight>-1) {
928
	if (currentHighlight>-1) {
929
		if (currentHighlight<[theTextStorage length]) {
929
		if (currentHighlight<[theTextStorage length]) {
930
			NSLayoutManager *lm = [self layoutManager];
930
			NSLayoutManager *lm = [self layoutManager];
931
			if (lm) {
931
			if (lm) {
932
				NSRange fr = NSMakeRange(currentHighlight,1);
932
				NSRange fr = NSMakeRange(currentHighlight,1);
933
				NSDictionary *d = [lm temporaryAttributesAtCharacterIndex:currentHighlight effectiveRange:&fr];
933
				NSDictionary *d = [lm temporaryAttributesAtCharacterIndex:currentHighlight effectiveRange:&fr];
934
				if (!d || [d objectForKey:NSBackgroundColorAttributeName]==nil) {
934
				if (!d || [d objectForKey:NSBackgroundColorAttributeName]==nil) {
935
					fr = NSMakeRange(0,[[self string] length]);
935
					fr = NSMakeRange(0,[[self string] length]);
936
					SLog(@"resetHighlights: attribute at %d not found, clearing all %d characters - better safe than sorry", currentHighlight, fr.length);
936
					SLog(@"resetHighlights: attribute at %d not found, clearing all %d characters - better safe than sorry", currentHighlight, fr.length);
937
				}
937
				}
938
				[lm removeTemporaryAttribute:NSBackgroundColorAttributeName forCharacterRange:fr];
938
				[lm removeTemporaryAttribute:NSBackgroundColorAttributeName forCharacterRange:fr];
939
			}
939
			}
940
		}
940
		}
941
		currentHighlight=-1;
941
		currentHighlight=-1;
942
	}
942
	}
943
}
943
}
944
 
944
 
945
-(void)highlightCharacter:(NSNumber*)loc
945
-(void)highlightCharacter:(NSNumber*)loc
946
{
946
{
947
	NSInteger pos = [loc intValue];
947
	NSInteger pos = [loc intValue];
948
 
948
 
949
	SLog(@"RScriptEditorTextView: highlightCharacter: %d", pos);
949
	SLog(@"RScriptEditorTextView: highlightCharacter: %d", pos);
950
 
950
 
951
	if (pos>=0 && pos<[[self string] length]) {
951
	if (pos>=0 && pos<[[self string] length]) {
952
 
952
 
953
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
953
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
954
		[self showFindIndicatorForRange:NSMakeRange(pos, 1)];
954
		[self showFindIndicatorForRange:NSMakeRange(pos, 1)];
955
#else
955
#else
956
		[self resetHighlights];
956
		[self resetHighlights];
957
		NSLayoutManager *lm = [self layoutManager];
957
		NSLayoutManager *lm = [self layoutManager];
958
		if (lm) {
958
		if (lm) {
959
			currentHighlight = pos;
959
			currentHighlight = pos;
960
			[lm setTemporaryAttributes:highlightColorAttr forCharacterRange:NSMakeRange(pos, 1)];
960
			[lm setTemporaryAttributes:highlightColorAttr forCharacterRange:NSMakeRange(pos, 1)];
961
			[self performSelector:@selector(resetBackgroundColor:) withObject:nil afterDelay:braceHighlightInterval];
961
			[self performSelector:@selector(resetBackgroundColor:) withObject:nil afterDelay:braceHighlightInterval];
962
		}
962
		}
963
 
963
 
964
#endif
964
#endif
965
 
965
 
966
	}
966
	}
967
	else SLog(@"highlightCharacter: attempt to set highlight %d beyond the text range 0:%d - I refuse!", pos, [[self string] length] - 1);
967
	else SLog(@"highlightCharacter: attempt to set highlight %d beyond the text range 0:%d - I refuse!", pos, [[self string] length] - 1);
968
}
968
}
969
 
969
 
970
-(void)resetBackgroundColor:(id)sender
970
-(void)resetBackgroundColor:(id)sender
971
{
971
{
972
	[self resetHighlights];
972
	[self resetHighlights];
973
}
973
}
974
 
974
 
975
/**
975
/**
976
 * Scrollview delegate after the textView's view port was changed.
976
 * Scrollview delegate after the textView's view port was changed.
977
 * Manily used to update the syntax highlighting for a large text size
977
 * Manily used to update the syntax highlighting for a large text size
978
 */
978
 */
979
- (void)boundsDidChangeNotification:(NSNotification *)notification
979
- (void)boundsDidChangeNotification:(NSNotification *)notification
980
{
980
{
981
 
981
 
982
	if(startListeningToBoundChanges) {
982
	if(startListeningToBoundChanges) {
983
 
983
 
984
		breakSyntaxHighlighting = 1;
984
		breakSyntaxHighlighting = 1;
985
 
985
 
986
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
986
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
987
									selector:@selector(doSyntaxHighlighting) 
987
									selector:@selector(doSyntaxHighlighting) 
988
									object:nil];
988
									object:nil];
989
 
989
 
990
		if(![theTextStorage changeInLength]) {
990
		if(![theTextStorage changeInLength]) {
991
			if([[theTextStorage string] length] > 120000)
991
			if([[theTextStorage string] length] > 120000)
992
				breakSyntaxHighlighting = 2;
992
				breakSyntaxHighlighting = 2;
993
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.08];
993
			[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.08];
994
		}
994
		}
995
		if(lineNumberingEnabled) {
995
		if(lineNumberingEnabled) {
996
			[NSObject cancelPreviousPerformRequestsWithTarget:[[self enclosingScrollView] verticalRulerView] 
996
			[NSObject cancelPreviousPerformRequestsWithTarget:[[self enclosingScrollView] verticalRulerView] 
997
										selector:@selector(refresh) 
997
										selector:@selector(refresh) 
998
										object:nil];
998
										object:nil];
999
			
999
			
1000
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.001f];
1000
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.001f];
1001
		}
1001
		}
1002
 
1002
 
1003
	}
1003
	}
1004
 
1004
 
1005
}
1005
}
1006
 
1006
 
1007
- (IBAction)undo:(id)sender
1007
- (IBAction)undo:(id)sender
1008
{
1008
{
1009
	if([[self undoManager] canUndo]) {
1009
	if([[self undoManager] canUndo]) {
1010
		[[self undoManager] undo];
1010
		[[self undoManager] undo];
1011
		if(lineNumberingEnabled)
1011
		if(lineNumberingEnabled)
1012
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1012
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1013
	}
1013
	}
1014
}
1014
}
1015
 
1015
 
1016
- (IBAction)redo:(id)sender
1016
- (IBAction)redo:(id)sender
1017
{
1017
{
1018
	if([[self undoManager] canRedo]) {
1018
	if([[self undoManager] canRedo]) {
1019
		[[self undoManager] redo];
1019
		[[self undoManager] redo];
1020
		if(lineNumberingEnabled)
1020
		if(lineNumberingEnabled)
1021
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1021
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1022
	}
1022
	}
1023
}
1023
}
1024
 
1024
 
1025
#pragma mark -
1025
#pragma mark -
1026
#pragma mark Folding
1026
#pragma mark Folding
1027
 
1027
 
1028
/*
1028
/*
1029
The idea of code folding is to replace the folded range while layouting by NSControlGlyphs
1029
The idea of code folding is to replace the folded range while layouting by NSControlGlyphs
1030
which will be rendered as zero width glyphs. This has the advantage that all text actions like 
1030
which will be rendered as zero width glyphs. This has the advantage that all text actions like 
1031
copying, line numbering, etc. works without additional stuff.
1031
copying, line numbering, etc. works without additional stuff.
1032
 
1032
 
1033
For now it is only possible to fold a block if:
1033
For now it is only possible to fold a block if:
1034
- the starting { is placed at the end of a line (or with a following comment)
1034
- the starting { is placed at the end of a line (or with a following comment)
1035
- there's only ONE starting { in that line and NO }
1035
- there's only ONE starting { in that line and NO }
1036
- the ending } is placed at the of a line (or with a following comment)
1036
- the ending } is placed at the of a line (or with a following comment)
1037
- there's only ONE ending } in that line and NO {
1037
- there's only ONE ending } in that line and NO {
1038
 
1038
 
1039
Due to speed issues all folded ranges will be stored in a 3d C array of the size
1039
Due to speed issues all folded ranges will be stored in a 3d C array of the size
1040
R_MAX_FOLDED_ITEMS = 1024 defined in RScriptEditorTextStorage.h whereby index:
1040
R_MAX_FOLDED_ITEMS = 1024 defined in RScriptEditorTextStorage.h whereby index:
1041
0 - range location
1041
0 - range location
1042
1 - range length
1042
1 - range length
1043
2 - location + length (pre-calculate for speed)
1043
2 - location + length (pre-calculate for speed)
1044
 
1044
 
1045
If the user locates the cursor inside a folded range or an action will locate the cursor
1045
If the user locates the cursor inside a folded range or an action will locate the cursor
1046
inside such a range (go to line, find something) the folded range will be unfolded.
1046
inside such a range (go to line, find something) the folded range will be unfolded.
1047
... for more info ask Hans-J. Bibiko
1047
... for more info ask Hans-J. Bibiko
1048
*/
1048
*/
1049
 
1049
 
1050
- (IBAction)unfoldCurrentBlock:(id)sender
1050
- (IBAction)unfoldCurrentBlock:(id)sender
1051
{
1051
{
1052
	NSUInteger caretPosition = [self selectedRange].location;
1052
	NSUInteger caretPosition = [self selectedRange].location;
1053
 
1053
 
1054
	NSRange r = [[self string] lineRangeForRange:NSMakeRange(caretPosition, 0)];
1054
	NSRange r = [[self string] lineRangeForRange:NSMakeRange(caretPosition, 0)];
1055
 
1055
 
1056
	if([theTextStorage foldedAtIndex:NSMaxRange(r)] > -1) {
1056
	if([theTextStorage foldedAtIndex:NSMaxRange(r)] > -1) {
1057
		[self unfoldLinesContainingCharacterAtIndex:NSMaxRange(r)];
1057
		[self unfoldLinesContainingCharacterAtIndex:NSMaxRange(r)];
1058
		return;
1058
		return;
1059
	}
1059
	}
1060
	if([theTextStorage foldedAtIndex:r.location] > -1) {
1060
	if([theTextStorage foldedAtIndex:r.location] > -1) {
1061
		[self unfoldLinesContainingCharacterAtIndex:r.location];
1061
		[self unfoldLinesContainingCharacterAtIndex:r.location];
1062
		return;
1062
		return;
1063
	}
1063
	}
1064
}
1064
}
1065
 
1065
 
1066
- (IBAction)foldCurrentBlock:(id)sender
1066
- (IBAction)foldCurrentBlock:(id)sender
1067
{
1067
{
1068
	NSUInteger caretPosition = [self selectedRange].location;
1068
	NSUInteger caretPosition = [self selectedRange].location;
1069
	NSInteger foldItem = 0;
1069
	NSInteger foldItem = 0;
1070
	unichar c;
1070
	unichar c;
1071
 
1071
 
1072
	NSRange r = [[self string] lineRangeForRange:NSMakeRange(caretPosition, 0)];
1072
	NSRange r = [[self string] lineRangeForRange:NSMakeRange(caretPosition, 0)];
1073
 
1073
 
1074
	foldItem = [self foldStatusAtIndex:NSMaxRange(r)-2];
1074
	foldItem = [self foldStatusAtIndex:NSMaxRange(r)-2];
1075
	if(foldItem == 1) { // is current line set to ▼ set caret to end of line
1075
	if(foldItem == 1) { // is current line set to ▼ set caret to end of line
1076
		caretPosition = NSMaxRange(r)-1;
1076
		caretPosition = NSMaxRange(r)-1;
1077
	} else { // otherwise set caret to begin of line
1077
	} else { // otherwise set caret to begin of line
1078
		caretPosition = r.location;
1078
		caretPosition = r.location;
1079
	}
1079
	}
1080
	
1080
	
1081
	NSUInteger stringLength = [[self string] length];
1081
	NSUInteger stringLength = [[self string] length];
1082
	if(!stringLength) return;
1082
	if(!stringLength) return;
1083
	if(caretPosition == 0 || caretPosition >= [[self string] length]) return;
1083
	if(caretPosition == 0 || caretPosition >= [[self string] length]) return;
1084
		
1084
		
1085
	CFStringRef parserStringRef = (CFStringRef)[self string];
1085
	CFStringRef parserStringRef = (CFStringRef)[self string];
1086
 
1086
 
1087
	unichar co = '{'; // opening char
1087
	unichar co = '{'; // opening char
1088
	unichar cc = '}'; // closing char
1088
	unichar cc = '}'; // closing char
1089
	
1089
	
1090
	NSInteger start = -1;
1090
	NSInteger start = -1;
1091
	NSInteger end = -1;
1091
	NSInteger end = -1;
1092
	NSInteger bracketCounter = 0;
1092
	NSInteger bracketCounter = 0;
1093
 
1093
 
1094
	c = CFStringGetCharacterAtIndex(parserStringRef, caretPosition);
1094
	c = CFStringGetCharacterAtIndex(parserStringRef, caretPosition);
1095
	if(c == cc)
1095
	if(c == cc)
1096
		bracketCounter--;
1096
		bracketCounter--;
1097
	if(c == co)
1097
	if(c == co)
1098
		bracketCounter++;
1098
		bracketCounter++;
1099
 
1099
 
1100
	for(NSInteger i=caretPosition; i>=0; i--) {
1100
	for(NSInteger i=caretPosition; i>=0; i--) {
1101
		if([self parserContextForPosition:i] != pcExpression) continue;
1101
		if([self parserContextForPosition:i] != pcExpression) continue;
1102
		c = CFStringGetCharacterAtIndex(parserStringRef, i);
1102
		c = CFStringGetCharacterAtIndex(parserStringRef, i);
1103
		if(c == co) {
1103
		if(c == co) {
1104
			if(!bracketCounter) {
1104
			if(!bracketCounter) {
1105
				start = i;
1105
				start = i;
1106
				break;
1106
				break;
1107
			}
1107
			}
1108
			bracketCounter--;
1108
			bracketCounter--;
1109
		}
1109
		}
1110
		if(c == cc) {
1110
		if(c == cc) {
1111
			bracketCounter++;
1111
			bracketCounter++;
1112
		}
1112
		}
1113
	}
1113
	}
1114
	if(start < 0 ) return;
1114
	if(start < 0 ) return;
1115
 
1115
 
1116
	// go up for lines like "} else {"
1116
	// go up for lines like "} else {"
1117
	if(start && [self foldStatusAtIndex:start-1] == 0) {
1117
	if(start && [self foldStatusAtIndex:start-1] == 0) {
1118
		for(NSInteger i=start-1; i>=0; i--) {
1118
		for(NSInteger i=start-1; i>=0; i--) {
1119
			c = CFStringGetCharacterAtIndex(parserStringRef, i);
1119
			c = CFStringGetCharacterAtIndex(parserStringRef, i);
1120
			if(c == '\n' || c == '\r') break;
1120
			if(c == '\n' || c == '\r') break;
1121
			if([self parserContextForPosition:i] != pcExpression) continue;
1121
			if([self parserContextForPosition:i] != pcExpression) continue;
1122
			if(c == cc && i > 0) {
1122
			if(c == cc && i > 0) {
1123
				bracketCounter = 0;
1123
				bracketCounter = 0;
1124
				for(NSInteger j=i-1; j>=0; j--) {
1124
				for(NSInteger j=i-1; j>=0; j--) {
1125
					if([self parserContextForPosition:j] != pcExpression) continue;
1125
					if([self parserContextForPosition:j] != pcExpression) continue;
1126
					c = CFStringGetCharacterAtIndex(parserStringRef, j);
1126
					c = CFStringGetCharacterAtIndex(parserStringRef, j);
1127
					if(c == co) {
1127
					if(c == co) {
1128
						if(!bracketCounter) {
1128
						if(!bracketCounter) {
1129
							start = j;
1129
							start = j;
1130
							break;
1130
							break;
1131
						}
1131
						}
1132
						bracketCounter--;
1132
						bracketCounter--;
1133
					}
1133
					}
1134
					if(c == cc) {
1134
					if(c == cc) {
1135
						bracketCounter++;
1135
						bracketCounter++;
1136
					}
1136
					}
1137
				}
1137
				}
1138
				break;
1138
				break;
1139
			}
1139
			}
1140
		}
1140
		}
1141
	}		
1141
	}		
1142
 
1142
 
1143
 
1143
 
1144
	bracketCounter = 0;
1144
	bracketCounter = 0;
1145
	for(NSUInteger i=caretPosition; i<stringLength; i++) {
1145
	for(NSUInteger i=caretPosition; i<stringLength; i++) {
1146
		if([self parserContextForPosition:i] != pcExpression) continue;
1146
		if([self parserContextForPosition:i] != pcExpression) continue;
1147
		c = CFStringGetCharacterAtIndex(parserStringRef, i);
1147
		c = CFStringGetCharacterAtIndex(parserStringRef, i);
1148
		if(c == co) {
1148
		if(c == co) {
1149
			bracketCounter++;
1149
			bracketCounter++;
1150
		}
1150
		}
1151
		if(c == cc) {
1151
		if(c == cc) {
1152
			if(!bracketCounter) {
1152
			if(!bracketCounter) {
1153
				end = i+1;
1153
				end = i+1;
1154
				BOOL goAhead = NO;
1154
				BOOL goAhead = NO;
1155
				//go ahead for lines a la  "} else {"
1155
				//go ahead for lines a la  "} else {"
1156
				for(NSUInteger j=end; j<stringLength; j++) {
1156
				for(NSUInteger j=end; j<stringLength; j++) {
1157
					c = CFStringGetCharacterAtIndex(parserStringRef, j);
1157
					c = CFStringGetCharacterAtIndex(parserStringRef, j);
1158
					if(c == '\n' || c == '\r') {
1158
					if(c == '\n' || c == '\r') {
1159
						break;
1159
						break;
1160
					}
1160
					}
1161
					if(c == '\t' || c == ' ') {
1161
					if(c == '\t' || c == ' ') {
1162
						continue;
1162
						continue;
1163
					}
1163
					}
1164
					if([self parserContextForPosition:j] != pcExpression) continue;
1164
					if([self parserContextForPosition:j] != pcExpression) continue;
1165
					if(c == co) {
1165
					if(c == co) {
1166
						goAhead = YES;
1166
						goAhead = YES;
1167
						break;
1167
						break;
1168
					}
1168
					}
1169
				}
1169
				}
1170
				if(!goAhead) break;
1170
				if(!goAhead) break;
1171
			}
1171
			}
1172
			bracketCounter--;
1172
			bracketCounter--;
1173
		}
1173
		}
1174
	}
1174
	}
1175
 
1175
 
1176
	if(end < 0 || bracketCounter || end-start < 1) return;
1176
	if(end < 0 || bracketCounter || end-start < 1) return;
1177
 
1177
 
1178
	NSRange foldRange = NSMakeRange(start, end-start);
1178
	NSRange foldRange = NSMakeRange(start, end-start);
1179
	if(![theTextStorage existsFoldedRange:foldRange]) {
1179
	if(![theTextStorage existsFoldedRange:foldRange]) {
1180
		// set caret for ▲ line inside {} for scrolling
1180
		// set caret for ▲ line inside {} for scrolling
1181
		if(foldItem == 2)
1181
		if(foldItem == 2)
1182
			[self setSelectedRange:NSMakeRange(r.location, 0)];
1182
			[self setSelectedRange:NSMakeRange(r.location, 0)];
1183
		[self foldLinesInRange:foldRange blockMode:NO];
1183
		[self foldLinesInRange:foldRange blockMode:NO];
1184
	}
1184
	}
1185
 
1185
 
1186
}
1186
}
1187
 
1187
 
1188
- (IBAction)foldBlockAtLevel:(id)sender
1188
- (IBAction)foldBlockAtLevel:(id)sender
1189
{
1189
{
1190
 
1190
 
1191
	NSInteger level = [sender tag];
1191
	NSInteger level = [sender tag];
1192
	NSInteger bracketCounter = 0;
1192
	NSInteger bracketCounter = 0;
1193
	NSInteger start = 0;
1193
	NSInteger start = 0;
1194
	NSInteger end = 0;
1194
	NSInteger end = 0;
1195
	CFStringRef str = (CFStringRef)[self string];
1195
	CFStringRef str = (CFStringRef)[self string];
1196
	
1196
	
1197
	unichar c;
1197
	unichar c;
1198
	
1198
	
1199
	[[self undoManager] disableUndoRegistration];
1199
	[[self undoManager] disableUndoRegistration];
1200
	
1200
	
1201
	for(NSInteger i=0; i<[[self string] length]; i++) {
1201
	for(NSInteger i=0; i<[[self string] length]; i++) {
1202
		c = CFStringGetCharacterAtIndex(str, i);
1202
		c = CFStringGetCharacterAtIndex(str, i);
1203
		if([self parserContextForPosition:i] != pcExpression) continue;
1203
		if([self parserContextForPosition:i] != pcExpression) continue;
1204
		if(c == '{') {
1204
		if(c == '{') {
1205
			bracketCounter++;
1205
			bracketCounter++;
1206
			if([self foldStatusAtIndex:i] == 1) {
1206
			if([self foldStatusAtIndex:i] == 1) {
1207
				if(bracketCounter == level+1) {
1207
				if(bracketCounter == level+1) {
1208
					start = i;
1208
					start = i;
1209
				}
1209
				}
1210
			}
1210
			}
1211
			continue;
1211
			continue;
1212
		}
1212
		}
1213
		if(c == '}') {
1213
		if(c == '}') {
1214
			bracketCounter--;
1214
			bracketCounter--;
1215
			if([self foldStatusAtIndex:i] == 2) {
1215
			if([self foldStatusAtIndex:i] == 2) {
1216
				if(bracketCounter == level) {
1216
				if(bracketCounter == level) {
1217
					end = i;
1217
					end = i;
1218
					NSRange r = NSMakeRange(start, end - start+1);
1218
					NSRange r = NSMakeRange(start, end - start+1);
1219
					if(![theTextStorage existsFoldedRange:r])
1219
					if(![theTextStorage existsFoldedRange:r])
1220
						[self foldLinesInRange:r blockMode:YES];
1220
						[self foldLinesInRange:r blockMode:YES];
1221
				}
1221
				}
1222
				if(bracketCounter < 0) {
1222
				if(bracketCounter < 0) {
1223
					NSBeep();
1223
					NSBeep();
1224
					return;
1224
					return;
1225
				}
1225
				}
1226
			}
1226
			}
1227
		}
1227
		}
1228
	}
1228
	}
1229
 
1229
 
1230
	[self didChangeText];
1230
	[self didChangeText];
1231
	
1231
	
1232
	// NSRange r = [[self layoutManager] characterRangeForGlyphRange:[[self layoutManager] 
1232
	// NSRange r = [[self layoutManager] characterRangeForGlyphRange:[[self layoutManager] 
1233
	// 									glyphRangeForBoundingRect:[scrollView documentVisibleRect] 
1233
	// 									glyphRangeForBoundingRect:[scrollView documentVisibleRect] 
1234
	// 											  inTextContainer:[self textContainer]] actualGlyphRange:NULL];
1234
	// 											  inTextContainer:[self textContainer]] actualGlyphRange:NULL];
1235
	// 
1235
	// 
1236
	// [theTextStorage ensureAttributesAreFixedInRange:r];
1236
	// [theTextStorage ensureAttributesAreFixedInRange:r];
1237
 
1237
 
1238
	if(lineNumberingEnabled)
1238
	if(lineNumberingEnabled)
1239
		[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1239
		[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1240
	
1240
	
1241
	[NSObject cancelPreviousPerformRequestsWithTarget:self 
1241
	[NSObject cancelPreviousPerformRequestsWithTarget:self 
1242
							selector:@selector(doSyntaxHighlighting) 
1242
							selector:@selector(doSyntaxHighlighting) 
1243
							object:nil];
1243
							object:nil];
1244
 
1244
 
1245
	[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.02f];
1245
	[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.02f];
1246
 
1246
 
1247
	[[self undoManager] enableUndoRegistration];
1247
	[[self undoManager] enableUndoRegistration];
1248
}
1248
}
1249
 
1249
 
1250
- (IBAction)unFoldAllBlocks:(id)sender
1250
- (IBAction)unFoldAllBlocks:(id)sender
1251
{
1251
{
1252
	[theTextStorage removeAllFoldedRanges];
1252
	[theTextStorage removeAllFoldedRanges];
1253
 
1253
 
1254
	[self didChangeText];
1254
	[self didChangeText];
1255
 
1255
 
1256
	// NSRange r = NSMakeRange(0, [[self string] length]);
1256
	// NSRange r = NSMakeRange(0, [[self string] length]);
1257
 
1257
 
1258
	// [theTextStorage fixAttributesInRange:r];
1258
	// [theTextStorage fixAttributesInRange:r];
1259
	// [theTextStorage fixAttachmentAttributeInRange:r];
1259
	// [theTextStorage fixAttachmentAttributeInRange:r];
1260
	// [theTextStorage ensureAttributesAreFixedInRange:r];
1260
	// [theTextStorage ensureAttributesAreFixedInRange:r];
1261
 
1261
 
1262
 
1262
 
1263
	if(lineNumberingEnabled)
1263
	if(lineNumberingEnabled)
1264
		[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1264
		[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1265
 
1265
 
1266
	breakSyntaxHighlighting = 1;
1266
	breakSyntaxHighlighting = 1;
1267
	
1267
	
1268
	[NSObject cancelPreviousPerformRequestsWithTarget:self 
1268
	[NSObject cancelPreviousPerformRequestsWithTarget:self 
1269
							selector:@selector(doSyntaxHighlighting) 
1269
							selector:@selector(doSyntaxHighlighting) 
1270
							object:nil];
1270
							object:nil];
1271
 
1271
 
1272
	[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.01f];
1272
	[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.01f];
1273
}
1273
}
1274
 
1274
 
1275
- (void)refoldLinesInRange:(NSRange)range
1275
- (void)refoldLinesInRange:(NSRange)range
1276
{
1276
{
1277
 
1277
 
1278
	NSInteger foldId = [theTextStorage registerFoldedRange:range];
1278
	NSInteger foldId = [theTextStorage registerFoldedRange:range];
1279
 
1279
 
1280
	if(foldId < 0) {
1280
	if(foldId < 0) {
1281
		[RTooltip showWithObject:NLS(@"Maximum number of folded code fragments is reached.") atLocation:[NSEvent mouseLocation]];
1281
		[RTooltip showWithObject:NLS(@"Maximum number of folded code fragments is reached.") atLocation:[NSEvent mouseLocation]];
1282
		return;
1282
		return;
1283
	}
1283
	}
1284
 
1284
 
1285
	range.location++;
1285
	range.location++;
1286
	range.length -= 2;
1286
	range.length -= 2;
1287
 
1287
 
1288
	if(!range.length) return;
1288
	if(!range.length) return;
1289
	
1289
	
1290
	NSString *tooltip = nil;
1290
	NSString *tooltip = nil;
1291
	if(range.length < 300)
1291
	if(range.length < 300)
1292
		tooltip = [[self string] substringWithRange:range];
1292
		tooltip = [[self string] substringWithRange:range];
1293
	else
1293
	else
1294
		tooltip = [[[self string] substringWithRange:NSMakeRange(range.location, 300)] stringByAppendingString:@"\n…"];
1294
		tooltip = [[[self string] substringWithRange:NSMakeRange(range.location, 300)] stringByAppendingString:@"\n…"];
1295
 
1295
 
1296
	[theTextStorage beginEditing];
1296
	[theTextStorage beginEditing];
1297
	[theTextStorage addAttribute:NSCursorAttributeName value:[NSCursor arrowCursor] range:range];
1297
	[theTextStorage addAttribute:NSCursorAttributeName value:[NSCursor arrowCursor] range:range];
1298
	[theTextStorage addAttribute:NSToolTipAttributeName value:tooltip range:range];
1298
	[theTextStorage addAttribute:NSToolTipAttributeName value:tooltip range:range];
1299
	[theTextStorage endEditing];
1299
	[theTextStorage endEditing];
1300
 
1300
 
1301
}
1301
}
1302
 
1302
 
1303
- (BOOL)foldLinesInRange:(NSRange)range blockMode:(BOOL)blockMode
1303
- (BOOL)foldLinesInRange:(NSRange)range blockMode:(BOOL)blockMode
1304
{
1304
{
1305
	if(range.length < 5) {
1305
	if(range.length < 5) {
1306
		return NO;
1306
		return NO;
1307
	}
1307
	}
1308
 
1308
 
1309
	NSInteger caretPosition = [self selectedRange].location;
1309
	NSInteger caretPosition = [self selectedRange].location;
1310
	BOOL caretWasInsideFoldedRange = NO;
1310
	BOOL caretWasInsideFoldedRange = NO;
1311
 
1311
 
1312
	// Check for valid folding range
1312
	// Check for valid folding range
1313
	// fold only range if { and } are the last chars at the line
1313
	// fold only range if { and } are the last chars at the line
1314
 
1314
 
1315
	NSString *selfStr = [self string];
1315
	NSString *selfStr = [self string];
1316
	NSRange startLineRange = [selfStr lineRangeForRange:NSMakeRange(range.location, 0)];
1316
	NSRange startLineRange = [selfStr lineRangeForRange:NSMakeRange(range.location, 0)];
1317
	NSRange endLineRange   = [selfStr lineRangeForRange:NSMakeRange(NSMaxRange(range), 0)];
1317
	NSRange endLineRange   = [selfStr lineRangeForRange:NSMakeRange(NSMaxRange(range), 0)];
1318
 
1318
 
1319
	if(!startLineRange.length || !endLineRange.length) {
1319
	if(!startLineRange.length || !endLineRange.length) {
1320
		return NO;
1320
		return NO;
1321
	}
1321
	}
1322
 
1322
 
1323
	// Do not fold a single line
1323
	// Do not fold a single line
1324
	if(startLineRange.location == endLineRange.location) {
1324
	if(startLineRange.location == endLineRange.location) {
1325
		return NO;
1325
		return NO;
1326
	}
1326
	}
1327
 
1327
 
1328
	NSInteger status;
1328
	NSInteger status;
1329
 
1329
 
1330
	status = [self foldStatusAtIndex:NSMaxRange(startLineRange)-2];	
1330
	status = [self foldStatusAtIndex:NSMaxRange(startLineRange)-2];	
1331
	if(status != 1) {
1331
	if(status != 1) {
1332
		return NO;
1332
		return NO;
1333
	}
1333
	}
1334
 
1334
 
1335
	unichar c = CFStringGetCharacterAtIndex((CFStringRef)selfStr, NSMaxRange(endLineRange)-1);
1335
	unichar c = CFStringGetCharacterAtIndex((CFStringRef)selfStr, NSMaxRange(endLineRange)-1);
1336
	if(c == '\n' || c == '\r')
1336
	if(c == '\n' || c == '\r')
1337
		status = [self foldStatusAtIndex:NSMaxRange(endLineRange)-2];
1337
		status = [self foldStatusAtIndex:NSMaxRange(endLineRange)-2];
1338
	else
1338
	else
1339
		status = [self foldStatusAtIndex:NSMaxRange(endLineRange)-1];	
1339
		status = [self foldStatusAtIndex:NSMaxRange(endLineRange)-1];	
1340
	if(status != 2) {
1340
	if(status != 2) {
1341
		return NO;
1341
		return NO;
1342
	}
1342
	}
1343
 
1343
 
1344
	if(caretPosition >= range.location && caretPosition < NSMaxRange(range)) {
1344
	if(caretPosition >= range.location && caretPosition < NSMaxRange(range)) {
1345
		[self setSelectedRange:NSMakeRange(NSMaxRange(range), 0)];
1345
		[self setSelectedRange:NSMakeRange(NSMaxRange(range), 0)];
1346
		caretWasInsideFoldedRange = YES;
1346
		caretWasInsideFoldedRange = YES;
1347
	}
1347
	}
1348
 
1348
 
1349
	NSInteger foldId = [theTextStorage registerFoldedRange:range];
1349
	NSInteger foldId = [theTextStorage registerFoldedRange:range];
1350
 
1350
 
1351
	if(foldId < 0) {
1351
	if(foldId < 0) {
1352
		[RTooltip showWithObject:NLS(@"Maximum number of folded code fragments is reached.") atLocation:[NSEvent mouseLocation]];
1352
		[RTooltip showWithObject:NLS(@"Maximum number of folded code fragments is reached.") atLocation:[NSEvent mouseLocation]];
1353
		return NO;
1353
		return NO;
1354
	}
1354
	}
1355
 
1355
 
1356
	range.location++;
1356
	range.location++;
1357
	range.length -= 2;
1357
	range.length -= 2;
1358
 
1358
 
1359
	if(!range.length) return NO;
1359
	if(!range.length) return NO;
1360
	
1360
	
1361
	if(!blockMode) {
1361
	if(!blockMode) {
1362
		[[self undoManager] disableUndoRegistration];
1362
		[[self undoManager] disableUndoRegistration];
1363
		if(![self shouldChangeTextInRange:range replacementString:nil]) {
1363
		if(![self shouldChangeTextInRange:range replacementString:nil]) {
1364
			[[self undoManager] enableUndoRegistration];
1364
			[[self undoManager] enableUndoRegistration];
1365
			return NO;
1365
			return NO;
1366
		}
1366
		}
1367
		[[self undoManager] enableUndoRegistration];
1367
		[[self undoManager] enableUndoRegistration];
1368
	}
1368
	}
1369
 
1369
 
1370
	NSString *tooltip = nil;
1370
	NSString *tooltip = nil;
1371
	if(range.length < 300)
1371
	if(range.length < 300)
1372
		tooltip = [[self string] substringWithRange:range];
1372
		tooltip = [[self string] substringWithRange:range];
1373
	else
1373
	else
1374
		tooltip = [[[self string] substringWithRange:NSMakeRange(range.location, 300)] stringByAppendingString:@"\n…"];
1374
		tooltip = [[[self string] substringWithRange:NSMakeRange(range.location, 300)] stringByAppendingString:@"\n…"];
1375
 
1375
 
1376
	[theTextStorage beginEditing];
1376
	[theTextStorage beginEditing];
1377
	[theTextStorage addAttribute:NSCursorAttributeName value:[NSCursor arrowCursor] range:range];
1377
	[theTextStorage addAttribute:NSCursorAttributeName value:[NSCursor arrowCursor] range:range];
1378
	[theTextStorage addAttribute:NSToolTipAttributeName value:tooltip range:range];
1378
	[theTextStorage addAttribute:NSToolTipAttributeName value:tooltip range:range];
1379
	[theTextStorage endEditing];
1379
	[theTextStorage endEditing];
1380
 
1380
 
1381
	if(!blockMode) {
1381
	if(!blockMode) {
1382
		[self didChangeText];
1382
		[self didChangeText];
1383
 
1383
 
1384
		if(caretWasInsideFoldedRange)
1384
		if(caretWasInsideFoldedRange)
1385
			[self scrollRangeToVisible:[self selectedRange]];
1385
			[self scrollRangeToVisible:[self selectedRange]];
1386
 
1386
 
1387
		// NSRange r = [[self layoutManager] characterRangeForGlyphRange:[[self layoutManager] 
1387
		// NSRange r = [[self layoutManager] characterRangeForGlyphRange:[[self layoutManager] 
1388
		// 									glyphRangeForBoundingRect:[scrollView documentVisibleRect] 
1388
		// 									glyphRangeForBoundingRect:[scrollView documentVisibleRect] 
1389
		// 											  inTextContainer:[self textContainer]] actualGlyphRange:NULL];
1389
		// 											  inTextContainer:[self textContainer]] actualGlyphRange:NULL];
1390
 
1390
 
1391
		// [theTextStorage ensureAttributesAreFixedInRange:r];
1391
		// [theTextStorage ensureAttributesAreFixedInRange:r];
1392
 
1392
 
1393
		if(lineNumberingEnabled)
1393
		if(lineNumberingEnabled)
1394
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1394
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1395
	
1395
	
1396
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
1396
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
1397
								selector:@selector(doSyntaxHighlighting) 
1397
								selector:@selector(doSyntaxHighlighting) 
1398
								object:nil];
1398
								object:nil];
1399
 
1399
 
1400
		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.02f];
1400
		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.02f];
1401
	}
1401
	}
1402
 
1402
 
1403
	return YES;
1403
	return YES;
1404
 
1404
 
1405
}
1405
}
1406
 
1406
 
1407
- (NSInteger)foldStatusAtIndex:(NSInteger)index
1407
- (NSInteger)foldStatusAtIndex:(NSInteger)index
1408
{
1408
{
1409
 
1409
 
1410
	if(index < 0 || index >= [[self string] length]) return 0;
1410
	if(index < 0 || index >= [[self string] length]) return 0;
1411
 
1411
 
1412
	NSInteger status = 0; // 0 = no; 1 = ▼; 2 = ▲
1412
	NSInteger status = 0; // 0 = no; 1 = ▼; 2 = ▲
1413
 
1413
 
1414
	NSInteger i = index;
1414
	NSInteger i = index;
1415
	NSInteger type;
1415
	NSInteger type;
1416
	NSString *selfStr = [self string];
1416
	NSString *selfStr = [self string];
1417
	unichar c;
1417
	unichar c;
1418
 
1418
 
1419
	BOOL isRd = [selfDelegate isRdDocument];
1419
	BOOL isRd = [selfDelegate isRdDocument];
1420
 
1420
 
1421
	unichar commentSign = (isRd) ? '%' : '#';
1421
	unichar commentSign = (isRd) ? '%' : '#';
1422
 
1422
 
1423
	// start checking from the end of a line
1423
	// start checking from the end of a line
1424
	while(i >= 0) {
1424
	while(i >= 0) {
1425
 
1425
 
1426
		c = CFStringGetCharacterAtIndex((CFStringRef)selfStr, i);
1426
		c = CFStringGetCharacterAtIndex((CFStringRef)selfStr, i);
1427
 
1427
 
1428
		// Check only one line
1428
		// Check only one line
1429
		if(c=='\n' || c=='\r') break;
1429
		if(c=='\n' || c=='\r') break;
1430
 
1430
 
1431
		// Ignore white spaces and comment sign
1431
		// Ignore white spaces and comment sign
1432
		if(c==' ' || c=='\t' || c==commentSign) {
1432
		if(c==' ' || c=='\t' || c==commentSign) {
1433
			i--;
1433
			i--;
1434
			continue;
1434
			continue;
1435
		}
1435
		}
1436
 
1436
 
1437
		type = [self parserContextForPosition:i];
1437
		type = [self parserContextForPosition:i];
1438
 
1438
 
1439
		// Ignore comments
1439
		// Ignore comments
1440
		if(type == pcComment || c==commentSign) {
1440
		if(type == pcComment || c==commentSign) {
1441
			i--;
1441
			i--;
1442
			continue;
1442
			continue;
1443
		}
1443
		}
1444
 
1444
 
1445
		// ======= Check for ▼ 
1445
		// ======= Check for ▼ 
1446
		if(c=='{' && type == pcExpression) {
1446
		if(c=='{' && type == pcExpression) {
1447
			status = 1;
1447
			status = 1;
1448
			// look for lines a la "} else {" - if so do not draw folding marker
1448
			// look for lines a la "} else {" - if so do not draw folding marker
1449
			i--;
1449
			i--;
1450
			while(i>=0) {
1450
			while(i>=0) {
1451
				c = CFStringGetCharacterAtIndex((CFStringRef)selfStr, i);
1451
				c = CFStringGetCharacterAtIndex((CFStringRef)selfStr, i);
1452
				if(c=='\n' || c=='\r') break;
1452
				if(c=='\n' || c=='\r') break;
1453
				if((c=='}' || c=='{')&& [self parserContextForPosition:i] == pcExpression) {
1453
				if((c=='}' || c=='{')&& [self parserContextForPosition:i] == pcExpression) {
1454
					status = 0;
1454
					status = 0;
1455
					break;
1455
					break;
1456
				}
1456
				}
1457
				i--;
1457
				i--;
1458
			}
1458
			}
1459
			break;
1459
			break;
1460
		}
1460
		}
1461
 
1461
 
1462
		// ======= Check for ▲
1462
		// ======= Check for ▲
1463
		if(c=='}') {
1463
		if(c=='}') {
1464
			status = 2;
1464
			status = 2;
1465
			i--;
1465
			i--;
1466
			while(i>=0) {
1466
			while(i>=0) {
1467
				c = CFStringGetCharacterAtIndex((CFStringRef)selfStr, i);
1467
				c = CFStringGetCharacterAtIndex((CFStringRef)selfStr, i);
1468
				if(c=='\n' || c=='\r') break;
1468
				if(c=='\n' || c=='\r') break;
1469
				if((c=='}' || c=='{')&& [self parserContextForPosition:i] == pcExpression) {
1469
				if((c=='}' || c=='{')&& [self parserContextForPosition:i] == pcExpression) {
1470
					status = 0;
1470
					status = 0;
1471
					break;
1471
					break;
1472
				}
1472
				}
1473
				if(isRd) {
1473
				if(isRd) {
1474
					if(c != '\t' || c != ' ') {
1474
					if(c != '\t' || c != ' ') {
1475
						status = 0;
1475
						status = 0;
1476
						break;
1476
						break;
1477
					}
1477
					}
1478
				}
1478
				}
1479
				i--;
1479
				i--;
1480
			}
1480
			}
1481
		}
1481
		}
1482
		break;
1482
		break;
1483
 
1483
 
1484
	}
1484
	}
1485
 
1485
 
1486
	return status;
1486
	return status;
1487
	
1487
	
1488
}
1488
}
1489
 
1489
 
1490
- (BOOL)unfoldLinesContainingCharacterAtIndex:(NSUInteger)charIndex
1490
- (BOOL)unfoldLinesContainingCharacterAtIndex:(NSUInteger)charIndex
1491
{
1491
{
1492
 
1492
 
1493
	NSInteger foldIndex = [theTextStorage foldedAtIndex:charIndex];
1493
	NSInteger foldIndex = [theTextStorage foldedAtIndex:charIndex];
1494
 
1494
 
1495
	if(foldIndex > -1) {
1495
	if(foldIndex > -1) {
1496
 
1496
 
1497
		NSRange range = [theTextStorage foldedRangeAtIndex:foldIndex];
1497
		NSRange range = [theTextStorage foldedRangeAtIndex:foldIndex];
1498
		[[self undoManager] disableUndoRegistration];
1498
		[[self undoManager] disableUndoRegistration];
1499
		if(![self shouldChangeTextInRange:range replacementString:nil]) {
1499
		if(![self shouldChangeTextInRange:range replacementString:nil]) {
1500
			[[self undoManager] enableUndoRegistration];
1500
			[[self undoManager] enableUndoRegistration];
1501
			return NO;
1501
			return NO;
1502
		}
1502
		}
1503
		[[self undoManager] enableUndoRegistration];
1503
		[[self undoManager] enableUndoRegistration];
1504
		
1504
		
1505
		[theTextStorage removeFoldedRangeWithIndex:foldIndex];
1505
		[theTextStorage removeFoldedRangeWithIndex:foldIndex];
1506
 
1506
 
1507
		[self didChangeText];
1507
		[self didChangeText];
1508
 
1508
 
1509
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
1509
		[NSObject cancelPreviousPerformRequestsWithTarget:self 
1510
								selector:@selector(doSyntaxHighlighting) 
1510
								selector:@selector(doSyntaxHighlighting) 
1511
								object:nil];
1511
								object:nil];
1512
 
1512
 
1513
		// NSRange r = [[self layoutManager] characterRangeForGlyphRange:[[self layoutManager] 
1513
		// NSRange r = [[self layoutManager] characterRangeForGlyphRange:[[self layoutManager] 
1514
		// 									glyphRangeForBoundingRect:[scrollView documentVisibleRect] 
1514
		// 									glyphRangeForBoundingRect:[scrollView documentVisibleRect] 
1515
		// 											  inTextContainer:[self textContainer]] actualGlyphRange:NULL];
1515
		// 											  inTextContainer:[self textContainer]] actualGlyphRange:NULL];
1516
		// 
1516
		// 
1517
		// [theTextStorage ensureAttributesAreFixedInRange:r];
1517
		// [theTextStorage ensureAttributesAreFixedInRange:r];
1518
 
1518
 
1519
		if(lineNumberingEnabled)
1519
		if(lineNumberingEnabled)
1520
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1520
			[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
1521
		
1521
		
1522
		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.02f];
1522
		[self performSelector:@selector(doSyntaxHighlighting) withObject:nil afterDelay:0.02f];
1523
 
1523
 
1524
		return YES;
1524
		return YES;
1525
	}
1525
	}
1526
	
1526
	
1527
	return NO;
1527
	return NO;
1528
 
1528
 
1529
}
1529
}
1530
 
1530
 
1531
- (void)mouseDown:(NSEvent *)event
1531
- (void)mouseDown:(NSEvent *)event
1532
{
1532
{
1533
 
1533
 
1534
	if(![theTextStorage isKindOfClass:[RScriptEditorTextStorage class]]) {
1534
	if(![theTextStorage isKindOfClass:[RScriptEditorTextStorage class]]) {
1535
		[super mouseDown:event];
1535
		[super mouseDown:event];
1536
		return;
1536
		return;
1537
	}
1537
	}
1538
	
1538
	
1539
	RScriptEditorLayoutManager *layoutManager = (RScriptEditorLayoutManager*)[self layoutManager];
1539
	RScriptEditorLayoutManager *layoutManager = (RScriptEditorLayoutManager*)[self layoutManager];
1540
	NSUInteger glyphIndex = [layoutManager glyphIndexForPoint:[self convertPointFromBase:[event locationInWindow]] inTextContainer:[self textContainer]];
1540
	NSUInteger glyphIndex = [layoutManager glyphIndexForPoint:[self convertPoint:[event locationInWindow] fromView:nil] inTextContainer:[self textContainer]];
1541
	
1541
	
1542
	// trigger unfolding if inside foldingAttachmentCell
1542
	// trigger unfolding if inside foldingAttachmentCell
1543
	if (glyphIndex < [layoutManager numberOfGlyphs]) {
1543
	if (glyphIndex < [layoutManager numberOfGlyphs]) {
1544
	
1544
	
1545
		NSUInteger charIndex = [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
1545
		NSUInteger charIndex = [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
1546
		NSInteger foldIndex  = [theTextStorage foldedForIndicatorAtIndex:charIndex];
1546
		NSInteger foldIndex  = [theTextStorage foldedForIndicatorAtIndex:charIndex];
1547
	
1547
	
1548
		if (foldIndex > -1) {
1548
		if (foldIndex > -1) {
1549
	
1549
	
1550
			NSInteger foldStart = [theTextStorage foldedRangeAtIndex:foldIndex].location+1;
1550
			NSInteger foldStart = [theTextStorage foldedRangeAtIndex:foldIndex].location+1;
1551
			NSTextAttachment *attachment = [theTextStorage attribute:NSAttachmentAttributeName atIndex:foldStart effectiveRange:NULL];
1551
			NSTextAttachment *attachment = [theTextStorage attribute:NSAttachmentAttributeName atIndex:foldStart effectiveRange:NULL];
1552
	
1552
	
1553
			if (attachment) {
1553
			if (attachment) {
1554
				NSTextAttachmentCell *cell = (NSTextAttachmentCell *)[attachment attachmentCell];
1554
				NSTextAttachmentCell *cell = (NSTextAttachmentCell *)[attachment attachmentCell];
1555
				NSRect cellFrame;
1555
				NSRect cellFrame;
1556
				NSPoint delta;
1556
				NSPoint delta;
1557
	
1557
	
1558
				glyphIndex = [layoutManager glyphIndexForCharacterAtIndex:foldStart];
1558
				glyphIndex = [layoutManager glyphIndexForCharacterAtIndex:foldStart];
1559
	
1559
	
1560
				cellFrame.origin = [self textContainerOrigin];
1560
				cellFrame.origin = [self textContainerOrigin];
1561
				cellFrame.size = [layoutManager attachmentSizeForGlyphAtIndex:glyphIndex];
1561
				cellFrame.size = [layoutManager attachmentSizeForGlyphAtIndex:glyphIndex];
1562
	
1562
	
1563
				delta = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange:NULL].origin;
1563
				delta = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange:NULL].origin;
1564
				cellFrame.origin.x += delta.x;
1564
				cellFrame.origin.x += delta.x;
1565
				cellFrame.origin.y += delta.y;
1565
				cellFrame.origin.y += delta.y;
1566
	
1566
	
1567
				cellFrame.origin.x += [layoutManager locationForGlyphAtIndex:glyphIndex].x;
1567
				cellFrame.origin.x += [layoutManager locationForGlyphAtIndex:glyphIndex].x;
1568
	
1568
	
1569
				if ([cell wantsToTrackMouseForEvent:event inRect:cellFrame ofView:self atCharacterIndex:foldStart] 
1569
				if ([cell wantsToTrackMouseForEvent:event inRect:cellFrame ofView:self atCharacterIndex:foldStart] 
1570
						&& [cell trackMouse:event inRect:cellFrame ofView:self atCharacterIndex:foldStart untilMouseUp:YES]) return;
1570
						&& [cell trackMouse:event inRect:cellFrame ofView:self atCharacterIndex:foldStart untilMouseUp:YES]) return;
1571
			}
1571
			}
1572
		}
1572
		}
1573
	}
1573
	}
1574
	
1574
	
1575
	[super mouseDown:event];
1575
	[super mouseDown:event];
1576
}
1576
}
1577
 
1577
 
1578
// - (void)setSelectedRanges:(NSArray *)ranges affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag
1578
// - (void)setSelectedRanges:(NSArray *)ranges affinity:(NSSelectionAffinity)affinity stillSelecting:(BOOL)stillSelectingFlag
1579
// {
1579
// {
1580
// 
1580
// 
1581
// 	if(!stillSelectingFlag) {
1581
// 	if(!stillSelectingFlag) {
1582
// 
1582
// 
1583
// 		if([ranges count] > 0) {
1583
// 		if([ranges count] > 0) {
1584
// 
1584
// 
1585
// 			// Adjust range for folded text chunks; additional checks will be made in
1585
// 			// Adjust range for folded text chunks; additional checks will be made in
1586
// 			// the self's delegate [RDocumentWinCtrl:textViewDidChangeSelection:]
1586
// 			// the self's delegate [RDocumentWinCtrl:textViewDidChangeSelection:]
1587
// 
1587
// 
1588
// 			NSRange range = [[ranges objectAtIndex:0] rangeValue];
1588
// 			NSRange range = [[ranges objectAtIndex:0] rangeValue];
1589
// 
1589
// 
1590
// 			if(!range.length) {
1590
// 			if(!range.length) {
1591
// 				[super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag];
1591
// 				[super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag];
1592
// 				return;
1592
// 				return;
1593
// 			}
1593
// 			}
1594
// 
1594
// 
1595
// 			NSRange glyphRange = [[self layoutManager] glyphRangeForCharacterRange:range actualCharacterRange:NULL];
1595
// 			NSRange glyphRange = [[self layoutManager] glyphRangeForCharacterRange:range actualCharacterRange:NULL];
1596
// 
1596
// 
1597
// 			if(glyphRange.location != range.location || glyphRange.length != range.length) {
1597
// 			if(glyphRange.location != range.location || glyphRange.length != range.length) {
1598
// 
1598
// 
1599
// 				if([ranges count] == 2)
1599
// 				if([ranges count] == 2)
1600
// 					glyphRange.length += [[ranges objectAtIndex:1] rangeValue].length;
1600
// 					glyphRange.length += [[ranges objectAtIndex:1] rangeValue].length;
1601
// 
1601
// 
1602
// 				SLog(@"RScriptEditorTextView:setSelectedRanges: adjust range via glyph range from %@ to %@", NSStringFromRange(range), NSStringFromRange(glyphRange));
1602
// 				SLog(@"RScriptEditorTextView:setSelectedRanges: adjust range via glyph range from %@ to %@", NSStringFromRange(range), NSStringFromRange(glyphRange));
1603
// 
1603
// 
1604
// 				[super setSelectedRange:glyphRange];
1604
// 				[super setSelectedRange:glyphRange];
1605
// 				return;
1605
// 				return;
1606
// 
1606
// 
1607
// 			}
1607
// 			}
1608
// 		}
1608
// 		}
1609
// 	}
1609
// 	}
1610
// 
1610
// 
1611
// 	[super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag];
1611
// 	[super setSelectedRanges:ranges affinity:affinity stillSelecting:stillSelectingFlag];
1612
// 
1612
// 
1613
// }
1613
// }
1614
// 
1614
// 
1615
 
1615
 
1616
// - (void)setTypingAttributes:(NSDictionary *)attrs
1616
// - (void)setTypingAttributes:(NSDictionary *)attrs
1617
// {
1617
// {
1618
// 	// we don't want to store foldingAttributeId as a typing attribute
1618
// 	// we don't want to store foldingAttributeId as a typing attribute
1619
// 	if ([attrs objectForKey:foldingAttributeId]) {
1619
// 	if ([attrs objectForKey:foldingAttributeId]) {
1620
// 		NSMutableDictionary *copy = [[attrs mutableCopyWithZone:NULL] autorelease];
1620
// 		NSMutableDictionary *copy = [[attrs mutableCopyWithZone:NULL] autorelease];
1621
// 		[copy removeObjectForKey:foldingAttributeId];
1621
// 		[copy removeObjectForKey:foldingAttributeId];
1622
// 		attrs = copy;
1622
// 		attrs = copy;
1623
// 	}
1623
// 	}
1624
// 
1624
// 
1625
// 	[super setTypingAttributes:attrs];
1625
// 	[super setTypingAttributes:attrs];
1626
// }
1626
// }
1627
// 
1627
// 
1628
#pragma mark -
1628
#pragma mark -
1629
 
1629
 
1630
- (void)updatePreferences
1630
- (void)updatePreferences
1631
{
1631
{
1632
	
1632
	
1633
}
1633
}
1634
@end
1634
@end
1635
 
1635
 
1636
 
1636