git-svn-id: http://macvim.googlecode.com/svn/trunk@206 96c4425d-ca35-0410-94e5-3396d5...
[MacVim/jjgod.git] / MMTypesetter.m
blob388107dd9c1e3ed355194a06b0c5e53ce234e5bd
1 /* vi:set ts=8 sts=4 sw=4 ft=objc:
2  *
3  * VIM - Vi IMproved            by Bram Moolenaar
4  *                              MacVim GUI port by Bjorn Winckler
5  *
6  * Do ":help uganda"  in Vim to read copying and usage conditions.
7  * Do ":help credits" in Vim to see a list of people who contributed.
8  * See README.txt for an overview of the Vim source code.
9  */
11 #import "MMTypesetter.h"
12 #import "MMTextStorage.h"
13 #import "MacVim.h"
17 #if 0
18 @interface MMTypesetter (Private)
19 - (NSCharacterSet *)hiddenCharSet;
20 @end
21 #endif
25 @implementation MMTypesetter
28 // Layout glyphs so that each line fragment has a fixed size.
30 // It is assumed that the font for each character has been chosen so that every
31 // glyph has the right advancement (either 2*cellSize.width or half that,
32 // depending on whether it is a wide character or not).  This is taken care of
33 // by MMTextStorage in setAttributes:range: and in setFont:.  All that is left
34 // for the typesetter to do is to make sure each line fragment has the same
35 // height and that unwanted glyphs are hidden.
37 - (void)layoutGlyphsInLayoutManager:(NSLayoutManager *)lm
38                startingAtGlyphIndex:(unsigned)startGlyphIdx
39            maxNumberOfLineFragments:(unsigned)maxNumLines
40                      nextGlyphIndex:(unsigned *)nextGlyph
42     // TODO: Check that it really is an MMTextStorage.
43     MMTextStorage *ts = (MMTextStorage*)[lm textStorage];
44     NSTextView *tv = [lm firstTextView];
45     NSTextContainer *tc = [tv textContainer];
46     NSFont *font = [ts font];
47     NSString *text = [ts string];
48     unsigned textLen = [text length];
49     NSSize cellSize = [ts cellSize];
50     float baseline = [font descender];
52     if (!(ts && tv && tc && font && text && textLen))
53         return;
55     float baselineOffset = [[NSUserDefaults standardUserDefaults]
56             floatForKey:MMBaselineOffsetKey];
58     baseline += baselineOffset;
60     unsigned startCharIdx = [lm characterIndexForGlyphAtIndex:startGlyphIdx];
61     unsigned i, numberOfLines = 0, firstLine = 0;
62     NSRange firstLineRange = { 0, 0 };
64     // Find the first line and its range, and count the number of lines.  (This
65     // info could also be gleaned from MMTextStorage, but we do it here anyway
66     // to make absolutely sure everything is right.)
67     for (i = 0; i < textLen; numberOfLines++) {
68         NSRange lineRange = [text lineRangeForRange:NSMakeRange(i, 0)];
69         if (NSLocationInRange(startCharIdx, lineRange)) {
70             firstLine = numberOfLines;
71             firstLineRange = lineRange;
72         }
74         i = NSMaxRange(lineRange);
75     }
77     // Perform line fragment generation one line at a time.
78     NSRange lineRange = firstLineRange;
79     unsigned endGlyphIdx = startGlyphIdx;
80     for (i = 0; i < maxNumLines && lineRange.length; ++i) {
81         NSRange glyphRange = [lm glyphRangeForCharacterRange:lineRange
82                                         actualCharacterRange:nil];
83         NSRect lineRect = { 0, (firstLine+i)*cellSize.height,
84                 cellSize.width*(lineRange.length-1), cellSize.height };
85         unsigned endLineIdx = NSMaxRange(lineRange);
86         NSPoint glyphPt = { 0, cellSize.height+baseline };
87         unsigned j;
89         endGlyphIdx = NSMaxRange(glyphRange);
91         [lm setTextContainer:tc forGlyphRange:glyphRange];
92         [lm setLineFragmentRect:lineRect forGlyphRange:glyphRange
93                        usedRect:lineRect];
94         [lm setLocation:glyphPt forStartOfGlyphRange:glyphRange];
96         // Hide end-of-line and non-zero space characters (there is one after
97         // every wide character).
98         for (j = lineRange.location; j < endLineIdx; ++j) {
99             unichar ch = [text characterAtIndex:j];
100             if (ch == 0x200b || ch == '\n') {
101                 NSRange range = { j, 1 };
102                 range = [lm glyphRangeForCharacterRange:range
103                                    actualCharacterRange:nil];
104                 [lm setNotShownAttribute:YES forGlyphAtIndex:range.location];
105             }
106         }
108         lineRange = [text lineRangeForRange:NSMakeRange(endLineIdx, 0)];
109     }
111     if (nextGlyph)
112         *nextGlyph = endGlyphIdx;
115 @end // MMTypesetter
120 #if 0
121 @implementation MMTypesetter (Private)
123 - (NSCharacterSet *)hiddenCharSet
125     static NSCharacterSet *hiddenCharSet = nil;
127     if (!hiddenCharSet) {
128         NSString *string = [NSString stringWithFormat:@"%C\n", 0x200b];
129         hiddenCharSet = [NSCharacterSet
130                 characterSetWithCharactersInString:string];
131         [hiddenCharSet retain];
132     }
134     return hiddenCharSet;
137 @end // MMTypesetter (Private)
138 #endif