The R Project SVN R-packages

Rev

Rev 6438 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 6438 Rev 7927
Line 25... Line 25...
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
 *  Created by Simon Urbanek on 5/11/05.
29
 *  Created by Simon Urbanek on 5/11/05.
30
 *  $Id: RTextView.m 6438 2013-02-06 20:39:41Z urbaneks $
30
 *  $Id: RTextView.m 7927 2021-02-12 02:19:59Z urbaneks $
31
 */
31
 */
32
 
32
 
33
 
33
 
34
#import "RTextView.h"
34
#import "RTextView.h"
35
#import "HelpManager.h"
35
#import "HelpManager.h"
Line 51... Line 51...
51
static inline CGFloat RRectLeft(NSRect rectangle) { return rectangle.origin.x; }
51
static inline CGFloat RRectLeft(NSRect rectangle) { return rectangle.origin.x; }
52
static inline CGFloat RRectRight(NSRect rectangle) { return rectangle.origin.x+rectangle.size.width; }
52
static inline CGFloat RRectRight(NSRect rectangle) { return rectangle.origin.x+rectangle.size.width; }
53
static inline CGFloat RPointDistance(NSPoint a, NSPoint b) { return sqrtf( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ); }
53
static inline CGFloat RPointDistance(NSPoint a, NSPoint b) { return sqrtf( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) ); }
54
static inline NSPoint RPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NSMakePoint(a.x*(1.0f-t) + b.x*t, a.y*(1.0f-t) + b.y*t); }
54
static inline NSPoint RPointOnLine(NSPoint a, NSPoint b, CGFloat t) { return NSMakePoint(a.x*(1.0f-t) + b.x*t, a.y*(1.0f-t) + b.y*t); }
55
 
55
 
56
static inline int RPARSERCONTEXTFORPOSITION (RTextView* self, NSUInteger index) 
-
 
57
{
-
 
58
	typedef int (*RPARSERCONTEXTFORPOSITIONMethodPtr)(RTextView*, SEL, NSUInteger);
-
 
59
	static RPARSERCONTEXTFORPOSITIONMethodPtr _RPARSERCONTEXTFORPOSITION;
-
 
60
	if (!_RPARSERCONTEXTFORPOSITION) _RPARSERCONTEXTFORPOSITION = (RPARSERCONTEXTFORPOSITIONMethodPtr)[self methodForSelector:@selector(parserContextForPosition:)];
-
 
61
	int r = _RPARSERCONTEXTFORPOSITION(self, @selector(parserContextForPosition:), index);
-
 
62
	return r;
-
 
63
}
-
 
64
 
-
 
65
 
-
 
66
// declared external
56
// declared external
67
BOOL RTextView_autoCloseBrackets = YES;
57
BOOL RTextView_autoCloseBrackets = YES;
68
 
58
 
69
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
59
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
70
// declare the following methods to avoid compiler warnings
60
// declare the following methods to avoid compiler warnings
Line 80... Line 70...
80
#pragma mark -
70
#pragma mark -
81
#pragma mark Private API
71
#pragma mark Private API
82
 
72
 
83
@interface RTextView (Private)
73
@interface RTextView (Private)
84
 
74
 
85
- (void)selectMatchingPairAt:(int)position;
75
- (void)selectMatchingPairAt:(NSInteger)position;
86
- (NSString*)functionNameForCurrentScope;
76
- (NSString*)functionNameForCurrentScope;
87
 
77
 
88
@end
78
@end
89
 
79
 
90
#pragma mark -
80
#pragma mark -
Line 283... Line 273...
283
		return;
273
		return;
284
	}
274
	}
285
 
275
 
286
	NSString *rc = [theEvent charactersIgnoringModifiers];
276
	NSString *rc = [theEvent charactersIgnoringModifiers];
287
	NSString *cc = [theEvent characters];
277
	NSString *cc = [theEvent characters];
288
	unsigned int modFlags = [theEvent modifierFlags];
278
	unsigned long modFlags = [theEvent modifierFlags];
289
	long allFlags = (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask);
279
	long allFlags = (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask);
290
	long curFlags = (modFlags & allFlags);
280
	long curFlags = (modFlags & allFlags);
291
 
281
 
292
	BOOL hilite = NO;
282
	BOOL hilite = NO;
293
 
283
 
294
	SLog(@"RTextView: keyDown: %@ *** \"%@\" %d", theEvent, rc, modFlags);
284
	SLog(@"RTextView: keyDown: %@ *** \"%@\" %lx", theEvent, rc, modFlags);
295
 
285
 
296
	if([rc length] && [undoBreakTokensSet characterIsMember:[rc characterAtIndex:0]]) [self breakUndoCoalescing];
286
	if([rc length] && [undoBreakTokensSet characterIsMember:[rc characterAtIndex:0]]) [self breakUndoCoalescing];
297
 
287
 
298
	if ([rc isEqual:@"."] && (modFlags&allFlags)==NSControlKeyMask) {
288
	if ([rc isEqual:@"."] && (modFlags&allFlags)==NSControlKeyMask) {
299
		SLog(@" - send complete: to self");
289
		SLog(@" - send complete: to self");
300
		[self complete:self];
290
		[self complete:self];
301
		return;
291
		return;
302
	}
292
	}
303
	if ([rc isEqual:@"="]) {
293
	if ([rc isEqual:@"="]) {
304
		int mf = modFlags&allFlags;
294
		long mf = modFlags & allFlags;
305
		if ( mf ==NSControlKeyMask) {
295
		if ( mf ==NSControlKeyMask) {
306
			[self breakUndoCoalescing];
296
			[self breakUndoCoalescing];
307
			[self insertText:@"<-"];
297
			[self insertText:@"<-"];
308
			return;
298
			return;
309
		}
299
		}
Line 549... Line 539...
549
/**
539
/**
550
 * Returns the parser context for the passed cursor position
540
 * Returns the parser context for the passed cursor position
551
 *
541
 *
552
 * @param position The cursor position to test
542
 * @param position The cursor position to test
553
 */
543
 */
554
- (int)parserContextForPosition:(int)position
544
- (int)parserContextForPosition:(NSInteger)position
555
{
545
{
556
 
546
 
557
	int context = pcExpression;
547
	int context = pcExpression;
558
 
548
 
559
	if (position < 1)
549
	if (position < 1)
Line 572... Line 562...
572
 
562
 
573
	// we do NOT support multi-line strings, so the line always starts as an expression
563
	// we do NOT support multi-line strings, so the line always starts as an expression
574
	if (lineStart == position)
564
	if (lineStart == position)
575
		return context;
565
		return context;
576
 
566
 
577
	SLog(@"RTextView: parserContextForPosition: %d, line start: %ld", position, lineStart);
567
	SLog(@"RTextView: parserContextForPosition: %ld, line start: %ld", (long)position, (long)lineStart);
578
 
568
 
579
	int i = lineStart;
569
	long i = lineStart;
580
	BOOL skip = NO;
570
	BOOL skip = NO;
581
	unichar c;
571
	unichar c;
582
	unichar commentSign = (isRdDocument) ? '%' : '#';
572
	unichar commentSign = (isRdDocument) ? '%' : '#';
583
	
573
	
584
	while (i < position) {
574
	while (i < position) {
Line 976... Line 966...
976
/**
966
/**
977
 * Selects matching pairs if the character before position and at position are linked
967
 * Selects matching pairs if the character before position and at position are linked
978
 *
968
 *
979
 * @param position The cursor position to test
969
 * @param position The cursor position to test
980
 */
970
 */
981
- (void)selectMatchingPairAt:(int)position
971
- (void)selectMatchingPairAt:(NSInteger)position
982
{
972
{
983
 
973
 
984
	if(position < 1 || position >= [[self string] length])
974
	if(position < 1 || position >= [[self string] length])
985
		return;
975
		return;
986
 
976
 
Line 1015... Line 1005...
1015
	NSString *parseString = [self string];
1005
	NSString *parseString = [self string];
1016
	NSRange  selectedRange = [self selectedRange];
1006
	NSRange  selectedRange = [self selectedRange];
1017
	NSRange parseRange = NSMakeRange(0, [parseString length]);
1007
	NSRange parseRange = NSMakeRange(0, [parseString length]);
1018
	NSInteger breakCounter = 1000;
1008
	NSInteger breakCounter = 1000;
1019
 
1009
 
1020
	int parentheses = 0;
1010
	int  parentheses = 0;
1021
	int index       = 0;
1011
	NSInteger index  = 0;
1022
 
1012
 
1023
	SLog(@"RTextView: functionNameForCurrentScope");
1013
	SLog(@"RTextView: functionNameForCurrentScope");
1024
 
1014
 
1025
	// if user selected something take the selection only; otherwise take the current word
1015
	// if user selected something take the selection only; otherwise take the current word
1026
	if (selectedRange.length) {
1016
	if (selectedRange.length) {
Line 1034... Line 1024...
1034
	SLog(@" - current word “%@”", helpString);
1024
	SLog(@" - current word “%@”", helpString);
1035
 
1025
 
1036
	// if a word was found and the word doesn't represent a numeric value
1026
	// if a word was found and the word doesn't represent a numeric value
1037
	// and a ( follows then return word
1027
	// and a ( follows then return word
1038
	if([helpString length] && ![[[NSNumber numberWithFloat:[helpString floatValue]] stringValue] isEqualToString:helpString]) {
1028
	if([helpString length] && ![[[NSNumber numberWithFloat:[helpString floatValue]] stringValue] isEqualToString:helpString]) {
1039
		int start = NSMaxRange(selectedRange);
1029
		NSInteger start = NSMaxRange(selectedRange);
1040
		if(start < [parseString length]) {
1030
		if(start < [parseString length]) {
1041
			BOOL found = NO;
1031
			BOOL found = NO;
1042
			int i = 0;
1032
			NSInteger i = 0;
1043
			int end = ([parseString length] > 100) ? 100 : [parseString length];
1033
			NSInteger end = ([parseString length] > 100) ? 100 : [parseString length];
1044
			unichar c;
1034
			unichar c;
1045
			for(i = start; i < end; i++) {
1035
			for(i = start; i < end; i++) {
1046
                if ((c = CFStringGetCharacterAtIndex((CFStringRef)parseString, i)) == '(') {
1036
                if ((c = CFStringGetCharacterAtIndex((CFStringRef)parseString, i)) == '(') {
1047
					found = YES;
1037
					found = YES;
1048
					break;
1038
					break;
Line 1101... Line 1091...
1101
	if(!found) {
1091
	if(!found) {
1102
		SLog(@" - parsing unsuccessfull; bail");
1092
		SLog(@" - parsing unsuccessfull; bail");
1103
		return nil;
1093
		return nil;
1104
	}
1094
	}
1105
 
1095
 
1106
	SLog(@" - first not closed ( found at index: %d", index);
1096
	SLog(@" - first not closed ( found at index: %ld", (long) index);
1107
 
1097
 
1108
	// check if we still are in the parse range; otherwise bail
1098
	// check if we still are in the parse range; otherwise bail
1109
	if(parseRange.location > index) {
1099
	if(parseRange.location > index) {
1110
		SLog(@" - found index invalid - bail");
1100
		SLog(@" - found index invalid - bail");
1111
		return nil;
1101
		return nil;
Line 1123... Line 1113...
1123
				break;
1113
				break;
1124
			}
1114
			}
1125
		}
1115
		}
1126
	}
1116
	}
1127
 
1117
 
1128
	SLog(@" - function name found at index: %d", index);
1118
	SLog(@" - function name found at index: %ld", (long) index);
1129
 
1119
 
1130
	// check if we still are in the parse range; otherwise bail
1120
	// check if we still are in the parse range; otherwise bail
1131
	if(parseRange.location > index) {
1121
	if(parseRange.location > index) {
1132
		SLog(@" - found index invalid - bail");
1122
		SLog(@" - found index invalid - bail");
1133
		return nil;
1123
		return nil;
Line 1185... Line 1175...
1185
	for (theCharIndex=0; theCharIndex<[strToConvert length]; theCharIndex++, theCharIndexInTextView++) {
1175
	for (theCharIndex=0; theCharIndex<[strToConvert length]; theCharIndex++, theCharIndexInTextView++) {
1186
 
1176
 
1187
		c = CFStringGetCharacterAtIndex((CFStringRef)strToConvert, theCharIndex);
1177
		c = CFStringGetCharacterAtIndex((CFStringRef)strToConvert, theCharIndex);
1188
		// if c is non-ASCII and inside of "" or '' quotes transform it
1178
		// if c is non-ASCII and inside of "" or '' quotes transform it
1189
		//  - this ignores all c inside of comments
1179
		//  - this ignores all c inside of comments
1190
		if (c > 127 && RPARSERCONTEXTFORPOSITION((RTextView*)self, theCharIndexInTextView) < pcStringBQ)
1180
        if (c > 127 && [(RTextView*)self parserContextForPosition: theCharIndexInTextView] < pcStringBQ)
1191
			[theEncodedString appendFormat: @"\\u%04x", c];
1181
			[theEncodedString appendFormat: @"\\u%04x", c];
1192
		else
1182
		else
1193
			[theEncodedString appendFormat: @"%C", c];
1183
			[theEncodedString appendFormat: @"%C", c];
1194
 
1184
 
1195
	}
1185
	}
Line 1248... Line 1238...
1248
 
1238
 
1249
	if ([menuItem action] == @selector(redo:))
1239
	if ([menuItem action] == @selector(redo:))
1250
		return ([[self undoManager] canRedo]);
1240
		return ([[self undoManager] canRedo]);
1251
 
1241
 
1252
	if ([menuItem action] == @selector(makeASCIIconform:))
1242
	if ([menuItem action] == @selector(makeASCIIconform:))
1253
		return ([self selectedRange].length || (([(RTextView*)self getRangeForCurrentWord].length) && RPARSERCONTEXTFORPOSITION((RTextView*)self, [self selectedRange].location) < pcStringBQ)) ? YES : NO;
1243
        return ([self selectedRange].length || (([(RTextView*)self getRangeForCurrentWord].length) && [(RTextView*)self parserContextForPosition:[self selectedRange].location] < pcStringBQ)) ? YES : NO;
1254
 
1244
 
1255
	if ([menuItem action] == @selector(unescapeUnicode:))
1245
	if ([menuItem action] == @selector(unescapeUnicode:))
1256
		return ([self selectedRange].length || ([(RTextView*)self getRangeForCurrentWord].length)) ? YES : NO;
1246
		return ([self selectedRange].length || ([(RTextView*)self getRangeForCurrentWord].length)) ? YES : NO;
1257
 
1247
 
1258
	return YES;
1248
	return YES;
Line 1359... Line 1349...
1359
			}
1349
			}
1360
			else {
1350
			else {
1361
 
1351
 
1362
				[env setObject:filepath forKey:kShellVarNameDraggedFilePath];
1352
				[env setObject:filepath forKey:kShellVarNameDraggedFilePath];
1363
				[env setObject:[[filepath stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat:@"^%@", curDir] withString:@""] stringByAbbreviatingWithTildeInPath] forKey:kShellVarNameDraggedRelativeFilePath];
1353
				[env setObject:[[filepath stringByReplacingOccurrencesOfRegex:[NSString stringWithFormat:@"^%@", curDir] withString:@""] stringByAbbreviatingWithTildeInPath] forKey:kShellVarNameDraggedRelativeFilePath];
1364
				[env setObject:[NSNumber numberWithInt:snip_cnt] forKey:kShellVarNameCurrentSnippetIndex];
1354
				[env setObject:[NSNumber numberWithInt:(int)snip_cnt] forKey:kShellVarNameCurrentSnippetIndex];
1365
 
1355
 
1366
				NSString *extension = [[filepath pathExtension] lowercaseString];
1356
				NSString *extension = [[filepath pathExtension] lowercaseString];
1367
 
1357
 
1368
				// handle *.R for source()
1358
				// handle *.R for source()
1369
				if([extension isEqualToString:@"r"]) {
1359
				if([extension isEqualToString:@"r"]) {
Line 2132... Line 2122...
2132
{
2122
{
2133
 
2123
 
2134
	if (curRange.length) return curRange;
2124
	if (curRange.length) return curRange;
2135
 
2125
 
2136
	NSString *str = [self string];
2126
	NSString *str = [self string];
2137
	int curLocation = curRange.location;
2127
	NSInteger curLocation = curRange.location;
2138
	int start = curLocation;
2128
	NSInteger start = curLocation;
2139
	int end = curLocation;
2129
	NSInteger end = curLocation;
2140
	unsigned int strLen = [[self string] length];
2130
	NSUInteger strLen = [[self string] length];
2141
 
2131
 
2142
	if(start) {
2132
	if(start) {
2143
		start--;
2133
		start--;
2144
		if(CFStringGetCharacterAtIndex((CFStringRef)str, start) != '\n' || CFStringGetCharacterAtIndex((CFStringRef)str, start) != '\r') {
2134
		if(CFStringGetCharacterAtIndex((CFStringRef)str, start) != '\n' || CFStringGetCharacterAtIndex((CFStringRef)str, start) != '\r') {
2145
			while([wordCharSet characterIsMember:CFStringGetCharacterAtIndex((CFStringRef)str, start)]) {
2135
			while([wordCharSet characterIsMember:CFStringGetCharacterAtIndex((CFStringRef)str, start)]) {