Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions runtime/doc/gui_mac.txt
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ They are only usable when GUI is active.
*macvim-options*
These are the non-standard options that MacVim supports:
'antialias' 'blurradius' 'fullscreen'
'fuoptions' 'macligatures' 'macmeta' 'macthinstrokes'
'toolbariconsize' 'transparency'
'fuoptions' 'macfontfeatures' 'macligatures' 'macmeta'
'macthinstrokes' 'toolbariconsize' 'transparency'

These are GUI-related Vim options that have MacVim-specific behaviors:
'guifont'
Expand Down
22 changes: 22 additions & 0 deletions runtime/doc/options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6026,6 +6026,28 @@ A jump table for the options with a short description can be found at |Q_op|.
{not supported}
No longer supported, as the Mac OS X GUI code was removed.

*'macfontfeatures'*
'macfontfeatures' string (default "")
global
{not in Vi}
{only available when compiled with GUI enabled on
Mac OS X}
Comma-separated list of OpenType font features to enable for the text
in the window. Each entry is a four-character OpenType feature tag,
optionally followed by "=" and a number. A bare tag is equivalent to
"tag=1"; use "tag=0" to disable a feature the font enables by
default. Example: >
:set macfontfeatures=cv01,cv09,ss03=2,zero
< This requires the selected 'guifont' to support the given features
(e.g. character variants "cv01"-"cv99" or stylistic sets
"ss01"-"ss20"). Features not supported by the font are ignored.
Set to an empty string to restore the font's default features.
Note: use 'macligatures' to control standard ligatures; that option
takes precedence over a "liga" entry here.
Note: Currently this option only has an effect if
'Use Core Text renderer' is enabled in the GUI preferences pane, and
requires Mac OS X v10.13 or later.

*'macligatures'* *'nomacligatures'*
'macligatures' boolean (default off)
global
Expand Down
1 change: 1 addition & 0 deletions runtime/doc/quickref.txt
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,7 @@ Short explanation of each option: *option-list*
'loadplugins' 'lpl' load plugin scripts when starting up
'luadll' name of the Lua dynamic library
'macatsui' Mac GUI: use ATSUI text drawing
'macfontfeatures' OpenType font features to enable (MacVim GUI only)
'macligatures' display ligatures (MacVim GUI only)
'macmeta' 'mmta' use option as meta key (MacVim GUI only)
'macthinstrokes' render the text lighter by using thin strokes (MacVim GUI only)
Expand Down
1 change: 1 addition & 0 deletions runtime/doc/tags
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,7 @@ $quote eval.txt /*$quote*
'lz' options.txt /*'lz'*
'ma' options.txt /*'ma'*
'macatsui' options.txt /*'macatsui'*
'macfontfeatures' options.txt /*'macfontfeatures'*
'macligatures' options.txt /*'macligatures'*
'macmeta' options.txt /*'macmeta'*
'macthinstrokes' options.txt /*'macthinstrokes'*
Expand Down
2 changes: 2 additions & 0 deletions runtime/optwin.vim
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,8 @@ if has("gui")
call <SID>BinOptionG("fullscreen", &fullscreen)
call append("$", "fuoptions\tcontrol how fullscreen mode should behave")
call <SID>OptionG("fuoptions", &fuoptions)
call append("$", "macfontfeatures\tOpenType font features to enable")
call <SID>OptionG("macfontfeatures", &macfontfeatures)
call append("$", "macligatures\tdisplay ligatures")
call <SID>BinOptionG("macligatures", &macligatures)
call append("$", "macmeta\tuse option as meta key")
Expand Down
1 change: 1 addition & 0 deletions src/MacVim/MMBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
- (void)setFullScreenBackgroundColor:(int)color;

- (void)setAntialias:(BOOL)antialias;
- (void)setFontFeatures:(NSString *)features;
- (void)setLigatures:(BOOL)ligatures;
- (void)setThinStrokes:(BOOL)thinStrokes;
- (void)setBlurRadius:(int)radius;
Expand Down
13 changes: 13 additions & 0 deletions src/MacVim/MMBackend.m
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,19 @@ - (void)setAntialias:(BOOL)antialias
[self queueMessage:msgid data:nil];
}

- (void)setFontFeatures:(NSString *)features
{
// NOTE: Unlike setFont:wide: an empty string must still be sent since it
// means "reset to the font's default features".
int len = (int)[features lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSMutableData *data = [NSMutableData data];
[data appendBytes:&len length:sizeof(int)];
if (len > 0)
[data appendBytes:[features UTF8String] length:len];

[self queueMessage:SetFontFeaturesMsgID data:data];
}

- (void)setLigatures:(BOOL)ligatures
{
int msgid = ligatures ? EnableLigaturesMsgID : DisableLigaturesMsgID;
Expand Down
3 changes: 3 additions & 0 deletions src/MacVim/MMCoreTextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ NS_ASSUME_NONNULL_BEGIN
BOOL antialias;
BOOL ligatures;
BOOL thinStrokes;
NSString *fontFeatures; ///< Raw 'macfontfeatures' value
NSArray *fontFeatureSettings; ///< Parsed kCTFontFeatureSettingsAttribute array, nil if none

BOOL forceRefreshFont; // when true, don't early out of setFont calls.

Expand Down Expand Up @@ -138,6 +140,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)setPreEditRow:(int)row column:(int)col;
- (void)setMouseShape:(int)shape;
- (void)setAntialias:(BOOL)state;
- (void)setFontFeatures:(NSString *)features;
- (void)setLigatures:(BOOL)state;
- (void)setThinStrokes:(BOOL)state;
- (void)setImControl:(BOOL)enable;
Expand Down
57 changes: 57 additions & 0 deletions src/MacVim/MMCoreTextView.m
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,23 @@ - (void)invertBlockFromRow:(int)row column:(int)col numRows:(int)nrows
return [@"m" sizeWithAttributes:a].width;
}

/// Returns a font derived from the supplied one with the given OpenType
/// feature settings (a kCTFontFeatureSettingsAttribute-style array) applied.
static NSFont *
fontWithFeatureSettings(NSFont *base, NSArray *settings)
{
if (settings == nil || base == nil)
return base;
CTFontDescriptorRef desc = CTFontDescriptorCreateWithAttributes(
(CFDictionaryRef)@{ (NSString *)kCTFontFeatureSettingsAttribute: settings });
CTFontRef derived = CTFontCreateCopyWithAttributes(
(CTFontRef)base, 0.0, NULL, desc);
CFRelease(desc);
if (derived == NULL)
return base;
return [(NSFont *)derived autorelease];
}

typedef struct {
unsigned color;
int shape;
Expand Down Expand Up @@ -284,6 +301,8 @@ - (void)dealloc
[characterStrings release]; characterStrings = nil;
[fontVariants release]; fontVariants = nil;
[characterLines release]; characterLines = nil;
[fontFeatures release]; fontFeatures = nil;
[fontFeatureSettings release]; fontFeatureSettings = nil;

[helper setTextView:nil];
[helper release]; helper = nil;
Expand Down Expand Up @@ -582,6 +601,43 @@ - (void)setAntialias:(BOOL)state
antialias = state;
}

- (void)setFontFeatures:(NSString *)features
{
if (fontFeatures == features || [fontFeatures isEqualToString:features])
return;
[fontFeatures release];
fontFeatures = [features copy];
[fontFeatureSettings release];
fontFeatureSettings = nil;

#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13
if (features.length > 0) {
if (@available(macos 10.13, *)) {
// Parse the 'macfontfeatures' value ("tag" or "tag=N" entries)
// into the array of dictionaries CoreText expects for
// kCTFontFeatureSettingsAttribute.
NSMutableArray *settings = [NSMutableArray array];
for (NSString *entry in [features componentsSeparatedByString:@","]) {
NSArray *kv = [entry componentsSeparatedByString:@"="];
NSString *tag = kv[0];
if (tag.length != 4)
continue; // already validated by Vim; be defensive
int value = kv.count > 1 ? [kv[1] intValue] : 1;
[settings addObject:@{
(NSString *)kCTFontOpenTypeFeatureTag: tag,
(NSString *)kCTFontOpenTypeFeatureValue: @(value),
}];
}
if (settings.count > 0)
fontFeatureSettings = [settings retain];
}
}
#endif

[fontVariants removeAllObjects];
[characterLines removeAllObjects];
}

- (void)setLigatures:(BOOL)state
{
ligatures = state;
Expand Down Expand Up @@ -2116,6 +2172,7 @@ - (NSFont *)fontVariantForTextFlags:(int)textFlags {
fontRef = [NSFontManager.sharedFontManager convertFont:fontRef toHaveTrait:NSFontItalicTrait];
if (textFlags & DRAW_BOLD)
fontRef = [NSFontManager.sharedFontManager convertFont:fontRef toHaveTrait:NSFontBoldTrait];
fontRef = fontWithFeatureSettings(fontRef, fontFeatureSettings);

fontVariants[cacheFlags] = fontRef;
}
Expand Down
1 change: 1 addition & 0 deletions src/MacVim/MMTextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
- (void)performBatchDrawWithData:(NSData *)data;
- (void)setMouseShape:(int)shape;
- (void)setAntialias:(BOOL)antialias;
- (void)setFontFeatures:(NSString *)features;
- (void)setLigatures:(BOOL)ligatures;
- (void)setThinStrokes:(BOOL)thinStrokes;
- (void)setImControl:(BOOL)enable;
Expand Down
5 changes: 5 additions & 0 deletions src/MacVim/MMTextView.m
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ - (void)setAntialias:(BOOL)state
antialias = state;
}

- (void)setFontFeatures:(NSString *)features
{
// Not supported by this renderer; only MMCoreTextView handles this.
}

- (void)setLigatures:(BOOL)state
{
ligatures = state;
Expand Down
11 changes: 11 additions & 0 deletions src/MacVim/MMVimController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,17 @@ - (void)handleMessage:(int)msgid data:(NSData *)data
[[[windowController vimView] textView] setAntialias:NO];
}
break;
case SetFontFeaturesMsgID:
{
const void *bytes = [data bytes];
int len = *((int*)bytes); bytes += sizeof(int);
NSString *features = len > 0
? [[[NSString alloc] initWithBytes:(void*)bytes length:len
encoding:NSUTF8StringEncoding] autorelease]
: @"";
[[[windowController vimView] textView] setFontFeatures:features];
}
break;
case EnableLigaturesMsgID:
{
[[[windowController vimView] textView] setLigatures:YES];
Expand Down
1 change: 1 addition & 0 deletions src/MacVim/MacVim.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,7 @@ extern const char * const MMVimMsgIDStrings[];
MSG(EnableThinStrokesMsgID) \
MSG(DisableThinStrokesMsgID) \
MSG(ShowDefinitionMsgID) \
MSG(SetFontFeaturesMsgID) \
MSG(LoopBackMsgID) /* Simple message that Vim will reflect back to MacVim */ \
MSG(LastMsgID) \

Expand Down
8 changes: 8 additions & 0 deletions src/MacVim/gui_macvim.m
Original file line number Diff line number Diff line change
Expand Up @@ -2134,6 +2134,14 @@
[[MMBackend sharedInstance] setAntialias:antialias];
}

void
gui_macvim_set_fontfeatures(char_u *features)
{
NSString *s = features != NULL ? [NSString stringWithVimString:features]
: @"";
[[MMBackend sharedInstance] setFontFeatures:s];
}

void
gui_macvim_set_ligatures(int ligatures)
{
Expand Down
40 changes: 40 additions & 0 deletions src/option.c
Original file line number Diff line number Diff line change
Expand Up @@ -5324,6 +5324,46 @@ did_set_fullscreen(optset_T *args)
#endif

#if defined(FEAT_GUI_MACVIM) || defined(PROTO)
/*
* Process the updated 'macfontfeatures' option value.
* The value is a comma-separated list of OpenType feature settings, each a
* four-character tag optionally followed by "=" and a non-negative number.
*/
char *
did_set_macfontfeatures(optset_T *args UNUSED)
{
char_u *p = p_macfontfeatures;

while (*p != NUL)
{
int i;

// OpenType tag: exactly 4 printable ASCII chars (not ',' or '=')
for (i = 0; i < 4; ++i)
if (p[i] < 0x20 || p[i] > 0x7e || p[i] == ',' || p[i] == '=')
return e_invalid_argument;
p += 4;
if (*p == '=')
{
++p;
if (!VIM_ISDIGIT(*p))
return e_invalid_argument;
while (VIM_ISDIGIT(*p))
++p;
}
if (*p == ',')
{
if (*++p == NUL)
return e_invalid_argument; // trailing comma
}
else if (*p != NUL)
return e_invalid_argument;
}

gui_macvim_set_fontfeatures(p_macfontfeatures);
return NULL;
}

/*
* Process the updated 'macligatures' option value.
*/
Expand Down
1 change: 1 addition & 0 deletions src/option.h
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ EXTERN int p_lpl; // 'loadplugins'
EXTERN char_u *p_luadll; // 'luadll'
#endif
#ifdef FEAT_GUI_MACVIM
EXTERN char_u *p_macfontfeatures; // 'macfontfeatures'
EXTERN int p_macligatures; // 'macligatures'
EXTERN int p_macthinstrokes; // 'macthinstrokes'
EXTERN long p_columnspace; // 'columnspace'
Expand Down
9 changes: 9 additions & 0 deletions src/optiondefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1775,6 +1775,15 @@ static struct vimoption options[] =
(char_u *)NULL, PV_NONE, NULL, NULL,
{(char_u *)"", (char_u *)0L}
SCTX_INIT},
{"macfontfeatures", NULL, P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP,
#ifdef FEAT_GUI_MACVIM
(char_u *)&p_macfontfeatures, PV_NONE, did_set_macfontfeatures, NULL,
{(char_u *)"", (char_u *)0L}
#else
(char_u *)NULL, PV_NONE, NULL, NULL,
{(char_u *)NULL, (char_u *)0L}
#endif
SCTX_INIT},
{"macligatures", NULL, P_BOOL|P_VI_DEF|P_RCLR,
#ifdef FEAT_GUI_MACVIM
(char_u *)&p_macligatures, PV_NONE, did_set_macligatures, NULL,
Expand Down
1 change: 1 addition & 0 deletions src/proto/gui_macvim.pro
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ void gui_mch_fuopt_update(void);
void gui_macvim_update_modified_flag(void);
void gui_macvim_add_to_find_pboard(char_u *pat);
void gui_macvim_set_antialias(int antialias);
void gui_macvim_set_fontfeatures(char_u *features);
void gui_macvim_set_ligatures(int ligatures);
void gui_macvim_set_thinstrokes(int thinStrokes);
void gui_macvim_set_blur(int blur);
Expand Down
1 change: 1 addition & 0 deletions src/proto/option.pro
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ char *did_set_antialias(optset_T *args);
char *did_set_blur(optset_T *args);
char *did_set_columnspace(optset_T *args);
char *did_set_fullscreen(optset_T *args);
char *did_set_macfontfeatures(optset_T *args);
char *did_set_macligatures(optset_T *args);
char *did_set_macthinstrokes(optset_T *args);
char *did_set_transparency(optset_T *args);
Expand Down
14 changes: 14 additions & 0 deletions src/testdir/test_macvim.vim
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ func Test_macvim_options_commands_exist()
call assert_true(exists('+blurradius'), 'Missing option "blurradius"')
call assert_true(exists('+fullscreen'), 'Missing option "fullscreen"')
call assert_true(exists('+fuoptions'), 'Missing option "fuoptions"')
call assert_true(exists('+macfontfeatures'), 'Missing option "macfontfeatures"')
call assert_true(exists('+macligatures'), 'Missing option "macligatures"')
call assert_true(exists('+macmeta'), 'Missing option "macmeta"')
call assert_true(exists('+macthinstrokes'), 'Missing option "macthinstrokes"')
Expand Down Expand Up @@ -75,4 +76,17 @@ func Test_macvim_invalid_options()
call assert_fails("let &transparency=101", 'E474:')

call assert_fails("let &fuoptions='abcdef'", 'E474:')

call assert_fails("set macfontfeatures=abc", 'E474:')
call assert_fails("set macfontfeatures=abcde", 'E474:')
call assert_fails("set macfontfeatures=cv01=x", 'E474:')
call assert_fails("set macfontfeatures=cv01,", 'E474:')
endfunc

" Test that 'macfontfeatures' accepts valid values and can be reset
func Test_macvim_macfontfeatures()
set macfontfeatures=cv01,ss03=2,zero=0
call assert_equal('cv01,ss03=2,zero=0', &macfontfeatures)
set macfontfeatures=
call assert_equal('', &macfontfeatures)
endfunc
2 changes: 2 additions & 0 deletions src/testdir/util/gen_opt_test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ let test_values = {
\
\ 'blurradius': [[], [-1]],
\ 'fuoptions': [[], ['xxx']],
\ 'macfontfeatures': [['', 'cv01', 'cv01,cv09', 'ss03=2', 'liga=0'],
\ ['xxx', 'cv1', 'cv01=', 'cv01=x', 'cv01,,cv02']],
\ 'transparency': [[], ['-1']],
\
"\ default behaviours
Expand Down
Loading