1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-10-27 10:23:12 +03:00

Implement update fg/bg/sp

This commit is contained in:
Tae Won Ha 2016-06-19 10:07:03 +02:00
parent edffb8956b
commit bbc0096019
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
6 changed files with 96 additions and 73 deletions

View File

@ -18,6 +18,7 @@
#import <nvim/event/signal.h>
#import <nvim/main.h>
#define pun_type(t, x) (*((t *)(&x)))
// We declare nvim_main because it's not declared in any header files of neovim
extern int nvim_main(int argc, char **argv);
@ -32,6 +33,10 @@ static uv_cond_t condition;
static id <NeoVimUiBridgeProtocol> neo_vim_osx_ui;
static unsigned int default_foreground = qDefaultForeground;
static unsigned int default_background = qDefaultBackground;
static unsigned int default_special = qDefaultSpecial;
typedef struct {
UIBridgeData *bridge;
Loop *loop;
@ -182,12 +187,12 @@ static void xpc_ui_highlight_set(UI *ui __unused, HlAttrs attrs) {
CellAttributes cellAttrs;
cellAttrs.fontTrait = trait;
unsigned int fg = attrs.foreground == -1 ? qDefaultForeground : *((unsigned int*)(&attrs.foreground));
unsigned int bg = attrs.background == -1 ? qDefaultBackground : *((unsigned int*)(&attrs.background));
unsigned int fg = attrs.foreground == -1 ? default_foreground : pun_type(unsigned int, attrs.foreground);
unsigned int bg = attrs.background == -1 ? default_background : pun_type(unsigned int, attrs.background);
cellAttrs.foreground = attrs.reverse ? bg : fg;
cellAttrs.background = attrs.reverse ? fg : bg;
cellAttrs.special = attrs.special == -1 ? qDefaultSpecial : *((unsigned int*)(&attrs.special));
cellAttrs.special = attrs.special == -1 ? default_special : pun_type(unsigned int, attrs.special);
[neo_vim_osx_ui highlightSet:cellAttrs];
}
@ -215,17 +220,26 @@ static void xpc_ui_flush(UI *ui __unused) {
}
static void xpc_ui_update_fg(UI *ui __unused, int fg) {
//printf("update fg\n");
// printf("update fg: %x\n", fg);
if (fg != -1) {
default_foreground = pun_type(unsigned int, fg);
}
[neo_vim_osx_ui updateForeground:fg];
}
static void xpc_ui_update_bg(UI *ui __unused, int bg) {
//printf("update bg\n");
// printf("update bg: %x\n", bg);
if (bg != -1) {
default_background = pun_type(unsigned int, bg);
}
[neo_vim_osx_ui updateBackground:bg];
}
static void xpc_ui_update_sp(UI *ui __unused, int sp) {
//printf("update sp\n");
// printf("update sp: %x\n", sp);
if (sp != -1) {
default_special = pun_type(unsigned int, sp);
}
[neo_vim_osx_ui updateSpecial:sp];
}
@ -365,7 +379,7 @@ static void wait_input_enqueue(void **argv) {
}
- (void)vimInput:(NSString *)input {
// we retain, but not release here since it will be released in wait_input_enqueue
// We retain, but not release here since it will be released in wait_input_enqueue.
loop_schedule(&main_loop, event_create(1, wait_input_enqueue, 1, [input retain]));
}

View File

@ -96,7 +96,10 @@ class Grid: CustomStringConvertible {
self.size = size
self.position = Position.zero
let emptyRow = Array(count: size.width, repeatedValue: Cell(string: " ", attrs: qEmptyCellAttributes))
let emptyCellAttrs = CellAttributes(fontTrait: .None,
foreground: self.foreground, background: self.background, special: self.special)
let emptyRow = Array(count: size.width, repeatedValue: Cell(string: " ", attrs: emptyCellAttrs))
self.cells = Array(count: size.height, repeatedValue: emptyRow)
}
@ -167,4 +170,4 @@ class Grid: CustomStringConvertible {
self.cells[i].replaceRange(region.left...region.right, with: clearedRow)
}
}
}
}

View File

@ -1,9 +1,11 @@
@import Cocoa;
@import CoreText;
CTFontRef lookupFont(NSMutableArray *fontCache, const unichar *chars, UniCharCount count, CTFontRef currFontRef);
CFAttributedStringRef attributedStringForString(NSString *string, const CTFontRef font, BOOL useLigatures);
UniCharCount fetchGlyphsAndAdvances(const CTLineRef line, CGGlyph *glyphs, CGSize *advances, UniCharCount length);
UniCharCount gatherGlyphs(CGGlyph glyphs[], UniCharCount count);
UniCharCount ligatureGlyphsForChars(const unichar *chars, CGGlyph *glyphs, CGPoint *positions, UniCharCount length, CTFontRef font);
void recurseDraw(const unichar *chars, CGGlyph *glyphs, CGPoint *positions, UniCharCount length, CGContextRef context, CTFontRef fontRef, NSMutableArray *fontCache, BOOL useLigatures);
void recurseDraw(
const unichar *chars,
CGGlyph *glyphs, CGPoint *positions, UniCharCount length,
CGContextRef context,
CTFontRef fontRef,
NSMutableArray *fontCache,
BOOL useLigatures
);

View File

@ -16,7 +16,7 @@
#import "MMCoreTextView.h"
CTFontRef
static CTFontRef
lookupFont(NSMutableArray *fontCache, const unichar *chars, UniCharCount count,
CTFontRef currFontRef)
{
@ -48,7 +48,7 @@ lookupFont(NSMutableArray *fontCache, const unichar *chars, UniCharCount count,
return newFontRef;
}
CFAttributedStringRef
static CFAttributedStringRef
attributedStringForString(NSString *string, const CTFontRef font,
BOOL useLigatures)
{
@ -66,7 +66,7 @@ attributedStringForString(NSString *string, const CTFontRef font,
(CFDictionaryRef)attrs);
}
UniCharCount
static UniCharCount
fetchGlyphsAndAdvances(const CTLineRef line, CGGlyph *glyphs, CGSize *advances,
UniCharCount length)
{
@ -96,7 +96,7 @@ fetchGlyphsAndAdvances(const CTLineRef line, CGGlyph *glyphs, CGSize *advances,
return offset;
}
UniCharCount
static UniCharCount
gatherGlyphs(CGGlyph glyphs[], UniCharCount count)
{
// Gather scattered glyphs that was happended by Surrogate pair chars
@ -112,7 +112,7 @@ gatherGlyphs(CGGlyph glyphs[], UniCharCount count)
return glyphCount;
}
UniCharCount
static UniCharCount
ligatureGlyphsForChars(const unichar *chars, CGGlyph *glyphs,
CGPoint *positions, UniCharCount length, CTFontRef font)
{

View File

@ -76,15 +76,18 @@ typedef struct {
- (void)flush;
/**
* Set the foreground color.
* Set the default foreground color.
*/
- (void)updateForeground:(int)fg;
/**
* Set the background color.
* Set the default background color.
*/
- (void)updateBackground:(int)bg;
/**
* Set the default special color, eg curly underline for spelling errors.
*/
- (void)updateSpecial:(int)sp;
- (void)suspend;
- (void)setTitle:(NSString *)title;

View File

@ -19,24 +19,22 @@ func != (left: CellAttributes, right: CellAttributes) -> Bool {
return !(left == right)
}
private struct RowFragment: CustomStringConvertible {
let row: Int
let range: Range<Int>
var description: String {
return "RowFragment<\(row): \(range)>"
extension CellAttributes: CustomStringConvertible {
public var description: String {
return "CellAttributes<fg: \(String(format: "%x", self.foreground)), bg: \(String(format: "%x", self.background)))"
}
}
private struct AttributedRowFragment: CustomStringConvertible {
/// Contiguous piece of cells of a row that has the same attributes.
private struct RowRun: CustomStringConvertible {
let row: Int
let range: Range<Int>
let attrs: CellAttributes
var description: String {
return "AttributedRowFragment<\(row): \(range)\n\(attrs)>"
return "RowRun<\(row): \(range)\n\(attrs)>"
}
}
@ -85,7 +83,7 @@ public class NeoVimView: NSView {
guard self.grid.hasData else {
return
}
let context = NSGraphicsContext.currentContext()!.CGContext
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
@ -93,7 +91,7 @@ public class NeoVimView: NSView {
let dirtyRects = self.rectsBeingDrawn()
self.attributedRowFragmentsIntersecting(rects: dirtyRects).forEach { rowFrag in
self.rowRunIntersecting(rects: dirtyRects).forEach { rowFrag in
let positions = rowFrag.range
// filter out the put(0, 0)s (after a wide character)
.filter { self.grid.cells[rowFrag.row][$0].string.characters.count > 0 }
@ -119,32 +117,7 @@ public class NeoVimView: NSView {
backgroundRect.fill()
}
private func attributedRowFragmentsIntersecting(rects rects: [CGRect]) -> [AttributedRowFragment] {
return self.rowFragmentsIntersecting(rects: rects)
.map { rowFrag -> [AttributedRowFragment] in
let row = rowFrag.row
let rowCells = self.grid.cells[rowFrag.row]
let range = rowFrag.range
let startIndex = range.startIndex
var result = [
AttributedRowFragment(row: row, range: startIndex...startIndex, attrs: rowCells[startIndex].attrs)
]
range.forEach { idx in
if rowCells[idx].attrs == result.last!.attrs {
let last = result.popLast()!
result.append(AttributedRowFragment(row: row, range: last.range.startIndex...idx, attrs: last.attrs))
} else {
result.append(AttributedRowFragment(row: row, range: idx...idx, attrs: rowCells[idx].attrs))
}
}
return result
}
.flatMap { $0 }
}
private func rowFragmentsIntersecting(rects rects: [CGRect]) -> [RowFragment] {
private func rowRunIntersecting(rects rects: [CGRect]) -> [RowRun] {
return rects
.map { rect -> Region in
let rowStart = Int(floor((self.frame.height - (rect.origin.y + rect.size.height)) / self.cellSize.height))
@ -153,10 +126,30 @@ public class NeoVimView: NSView {
let columnEnd = Int(ceil((rect.origin.x + rect.size.width) / self.cellSize.width)) - 1
return Region(top: rowStart, bottom: rowEnd, left: columnStart, right: columnEnd)
} // There can be overlaps between the Regions, but for the time being we ignore them.
.map { region -> [RowFragment] in
return (region.rowRange).map { RowFragment(row: $0, range: region.columnRange) }
}
.flatMap { $0 }
.map { region -> [RowRun] in
return (region.rowRange)
.map { row -> [RowRun] in
let range = region.columnRange
let rowCells = self.grid.cells[row]
let startIndex = range.startIndex
var result = [
RowRun(row: row, range: startIndex...startIndex, attrs: rowCells[startIndex].attrs)
]
range.forEach { idx in
if rowCells[idx].attrs == result.last!.attrs {
let last = result.popLast()!
result.append(RowRun(row: row, range: last.range.startIndex...idx, attrs: last.attrs))
} else {
result.append(RowRun(row: row, range: idx...idx, attrs: rowCells[idx].attrs))
}
}
return result
} // -> [[RowRun]]
.flatMap { $0 } // -> [RowRun]
} // -> [[RowRun]]
.flatMap { $0 } // -> [RowRun]
}
private func positionOnView(row: Int, column: Int) -> CGPoint {
@ -255,20 +248,19 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
Swift.print("### scroll count: \(count)")
gui {
// Swift.print("before scroll: \(self.grid)")
self.grid.scroll(Int(count))
// Swift.print("after scroll: \(self.grid)")
let top = CGFloat(self.grid.region.top)
let bottom = CGFloat(self.grid.region.bottom)
let left = CGFloat(self.grid.region.left)
let right = CGFloat(self.grid.region.right)
let region = self.grid.region
let top = CGFloat(region.top)
let bottom = CGFloat(region.bottom)
let left = CGFloat(region.left)
let right = CGFloat(region.right)
let width = right - left + 1
let height = bottom - top + 1
let rect = CGRect(x: left * self.cellSize.width, y: bottom * self.cellSize.height,
width: width * self.cellSize.width, height: height * self.cellSize.height)
width: width * self.cellSize.width, height: height * self.cellSize.height)
self.setNeedsDisplayInRect(rect)
}
}
@ -309,15 +301,24 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
}
public func updateForeground(fg: Int32) {
// Swift.print("### update fg: \(colorFromCode(fg))")
// Swift.print("### update fg: \(String(format: "%x", fg))")
gui {
self.grid.foreground = UInt32(bitPattern: fg)
}
}
public func updateBackground(bg: Int32) {
// Swift.print("### update bg: \(colorFromCode(bg, kind: .Background))")
// Swift.print("### update bg: \(String(format: "%x", bg))")
gui {
self.grid.background = UInt32(bitPattern: bg)
}
}
public func updateSpecial(sp: Int32) {
// Swift.print("### update sp: \(colorFromCode(sp, kind: .Special))")
// Swift.print("### update sp: \(String(format: "%x", sp)")
gui {
self.grid.special = UInt32(bitPattern: sp)
}
}
public func suspend() {