The R Project SVN R-packages

Rev

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

Rev Author Line No. Line
6128 bibiko 1
/*
2
 *  R.app : a Cocoa front end to: "R A Computer Language for Statistical Data Analysis"
3
 *  
4
 *  R.app Copyright notes:
5
 *                     Copyright (C) 2004-12  The R Foundation
6
 *                     written by Stefano M. Iacus and Simon Urbanek
7
 *
8
 *                  
9
 *  R Copyright notes:
10
 *                     Copyright (C) 1995-1996   Robert Gentleman and Ross Ihaka
11
 *                     Copyright (C) 1998-2001   The R Development Core Team
12
 *                     Copyright (C) 2002-2004   The R Foundation
13
 *
14
 *  This program is free software; you can redistribute it and/or modify
15
 *  it under the terms of the GNU General Public License as published by
16
 *  the Free Software Foundation; either version 2 of the License, or
17
 *  (at your option) any later version.
18
 *
19
 *  This program is distributed in the hope that it will be useful,
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 *  GNU General Public License for more details.
23
 *
24
 *  A copy of the GNU General Public License is available via WWW at
25
 *  http://www.gnu.org/copyleft/gpl.html.  You can also obtain it by
26
 *  writing to the Free Software Foundation, Inc., 59 Temple Place,
27
 *  Suite 330, Boston, MA  02111-1307  USA.
28
 *
29
 *  RScriptEditorGlyphGenerator.m
30
 *
31
 *  Created by Hans-J. Bibiko on 01/03/2012.
32
 *
33
 */
34
 
8070 urbaneks 35
#import "RGUI.h"
6128 bibiko 36
#import "RScriptEditorGlyphGenerator.h"
8070 urbaneks 37
#import "RScriptEditorTypeSetter.h"
6233 bibiko 38
#import "RScriptEditorTextStorage.h"
39
#import "RScriptEditorLayoutManager.h"
6128 bibiko 40
#import "PreferenceKeys.h"
41
 
42
@implementation RScriptEditorGlyphGenerator
43
 
6233 bibiko 44
- (id)init
45
{
46
	self = [super init];
6137 bibiko 47
 
6233 bibiko 48
	if (self != nil) {
6137 bibiko 49
		nullGlyph = NSNullGlyph;
6238 bibiko 50
		sizeOfNSGlyph = sizeof(NSGlyph);
6233 bibiko 51
	}
6137 bibiko 52
 
6233 bibiko 53
	return self;
54
}
6137 bibiko 55
 
6233 bibiko 56
- (void)dealloc{
57
	if(theTextStorage) [theTextStorage release];
58
	[super dealloc];
59
}
60
 
61
- (void)setTextStorage:(RScriptEditorTextStorage*)textStorage
62
{
63
	if(theTextStorage) [theTextStorage release];
64
	theTextStorage = [textStorage retain];
65
}
66
 
6128 bibiko 67
- (void)generateGlyphsForGlyphStorage:(id <NSGlyphStorage>)glyphStorage desiredNumberOfCharacters:(NSUInteger)nChars glyphIndex:(NSUInteger *)glyphIndex characterIndex:(NSUInteger *)charIndex
68
{
69
	// Stash the original requester
70
	_destination = glyphStorage;
71
	[[NSGlyphGenerator sharedGlyphGenerator] generateGlyphsForGlyphStorage:self desiredNumberOfCharacters:nChars glyphIndex:glyphIndex characterIndex:charIndex];
72
	_destination = nil;
73
}
74
 
6238 bibiko 75
#pragma mark -
76
#pragma mark NSGlyphStoragePrimitives
77
 
6128 bibiko 78
- (void)insertGlyphs:(const NSGlyph *)glyphs length:(NSUInteger)length forStartingGlyphAtIndex:(NSUInteger)glyphIndex characterIndex:(NSUInteger)charIndex
79
{
8075 urbaneks 80
	if (!_destination) return;
8070 urbaneks 81
	NSGlyph localBuffer[64]; /* stack-local buffer to avoid allocations */
6137 bibiko 82
	NSGlyph *buffer = NULL;
7824 urbaneks 83
	NSInteger folded = [theTextStorage foldedAtIndex: charIndex];
6128 bibiko 84
 
8070 urbaneks 85
	// SLog(@"%@ insertGlyphs: length:%d forStartingGlyphAtIndex:%d characterIndex:%d", self, (int) length, (int) glyphIndex, (int) charIndex);
86
 
87
	/* This part replaces the real glyphs with NSNullGlyph (empty) and/or NSControlGlyph (the symbol)
88
	   inside folded code.
89
 
90
	   FIXME: we only check whether the first glyph is inside a fold and then
91
	   replace the glyphs inside that fold. It is unclear if this can be called
92
	   with larger areas that include folds somewhere in the middle. Analogously,
93
	   it is unclear if there can be multiple folds in the requested glyph area.
94
	   Empirically, glyphs are inserted only for same attribues, so syntax highlighting
95
	   seems to help us here by splitting the text in a way that supports this
96
	   approach.
97
	 */
98
	 if (folded > -1) {
6233 bibiko 99
		NSRange effectiveRange = [theTextStorage foldedRangeAtIndex:folded];
8070 urbaneks 100
		/* fold range includes the encloding { }, so we only care if we are actually inside and it's non-empty */
101
		if (effectiveRange.length &&
102
			charIndex + length > effectiveRange.location + 1 &&
103
			charIndex < NSMaxRange(effectiveRange) - 1) {
104
			SLog(@"insertGlyphs: glyphs [%d..%d] (@char %d, len %d), inside folded range %@ thus will replace glyphs",
105
				 (int) glyphIndex, (int) (glyphIndex + length - 1), (int) charIndex, (int) length,
106
				 NSStringFromRange(effectiveRange));
107
 
108
			/* we will be replacing something, so have to get a buffer for the glyphs we return */
109
			NSUInteger size = sizeOfNSGlyph * length;
110
			buffer = (size > sizeof(localBuffer)) ? NSZoneMalloc(NULL, size) : localBuffer;
111
 
112
			NSUInteger nullEnd = NSMaxRange(effectiveRange) - charIndex - 1;
113
			if (nullEnd > length)
114
				nullEnd = length;
115
			NSUInteger nullStart = effectiveRange.location + 1 - charIndex;
116
			NSUInteger nullLength = nullEnd - nullStart;
117
			if (nullLength < length) /* some have to be retained, so copy all and then null */
118
				memcpy(buffer, glyphs, sizeOfNSGlyph * length);
119
			/* it is actually 4 but for safety include a fall-back ... */
120
			if (sizeOfNSGlyph == 4)
121
				memset_pattern4(buffer + nullStart, &nullGlyph, sizeOfNSGlyph * nullLength);
122
			else {
123
				size_t i = nullStart;
8072 urbaneks 124
				while (i < nullEnd) buffer[i++] = nullGlyph;
8070 urbaneks 125
			}
126
			/* the first glyph just after the { (position 1) is the visible glyph */
127
			NSInteger ctrlLocation = effectiveRange.location + 1 - charIndex;
128
			if (ctrlLocation >= 0 && ctrlLocation < length)
129
				buffer[ctrlLocation] = NSControlGlyph;
6233 bibiko 130
			glyphs = buffer;
131
		}
6128 bibiko 132
	}
133
 
134
	[_destination insertGlyphs:glyphs length:length forStartingGlyphAtIndex:glyphIndex characterIndex:charIndex];
135
 
8070 urbaneks 136
	if (buffer && buffer != localBuffer)
137
		NSZoneFree(NULL, buffer);
6128 bibiko 138
}
139
 
140
- (void)setIntAttribute:(NSInteger)attributeTag value:(NSInteger)val forGlyphAtIndex:(NSUInteger)glyphIndex
141
{
142
	[_destination setIntAttribute:attributeTag value:val forGlyphAtIndex:glyphIndex];
143
}
144
 
145
- (NSAttributedString *)attributedString
146
{
147
	return [_destination attributedString];
148
}
149
 
150
- (NSUInteger)layoutOptions
151
{
6238 bibiko 152
	return [_destination layoutOptions] | NSShowControlGlyphs;
6128 bibiko 153
}
154
 
155
@end