The Cocoa wrapper for Scintilla has a methods for setting colors:
- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor *) value {
- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString *) fromHTML {
These methods pass the parameter in wParam and the color in lParam. But some color setting messages in Scingtilla have no parameter and pass the color in wParam (SCI_SETCARETFORE for example). The color setter methods cannot set these colors. Two additional color setter methods need to be defined that pass the color in wParam.
static long NSColorToLong(NSColor* value)
{
if (value.colorSpaceName != NSDeviceRGBColorSpace)
value = [value colorUsingColorSpaceName: NSDeviceRGBColorSpace];
long red = static_cast<long>(value.redComponent * 255);
long green = static_cast<long>(value.greenComponent * 255);
long blue = static_cast<long>(value.blueComponent * 255);
long color = (blue << 16) + (green << 8) + red;
return color;
}
/**
* Specialized property setter for colors.
*/
- (void) setColorProperty: (int) property parameter: (long) parameter value: (NSColor *) value {
mBackend->WndProc(property, parameter, NSColorToLong(value));
}
- (void) setColorProperty: (int) property value: (NSColor *) value {
mBackend->WndProc(property, NSColorToLong(value), 0);
}
//--------------------------------------------------------------------------------------------------
static long HTMLtoLong(NSString* fromHTML)
{
if (fromHTML.length > 3 && [fromHTML characterAtIndex: 0] == '#') {
bool longVersion = fromHTML.length > 6;
int index = 1;
char value[3] = {0, 0, 0};
value[0] = static_cast<char>([fromHTML characterAtIndex: index++]);
if (longVersion)
value[1] = static_cast<char>([fromHTML characterAtIndex: index++]);
else
value[1] = value[0];
unsigned rawRed;
[[NSScanner scannerWithString: @(value)] scanHexInt: &rawRed];
value[0] = static_cast<char>([fromHTML characterAtIndex: index++]);
if (longVersion)
value[1] = static_cast<char>([fromHTML characterAtIndex: index++]);
else
value[1] = value[0];
unsigned rawGreen;
[[NSScanner scannerWithString: @(value)] scanHexInt: &rawGreen];
value[0] = static_cast<char>([fromHTML characterAtIndex: index++]);
if (longVersion)
value[1] = static_cast<char>([fromHTML characterAtIndex: index++]);
else
value[1] = value[0];
unsigned rawBlue;
[[NSScanner scannerWithString: @(value)] scanHexInt: &rawBlue];
long color = (rawBlue << 16) + (rawGreen << 8) + rawRed;
return color;
} else {
return -1;
}
}
/**
* Another color property setting, which allows to specify the color as string like in HTML
* documents (i.e. with leading # and either 3 hex digits or 6).
*/
- (void) setColorProperty: (int) property parameter: (long) parameter fromHTML: (NSString *) fromHTML {
long color = HTMLtoLong(fromHTML);
if (color >= 0)
mBackend->WndProc(property, parameter, color);
}
- (void) setColorProperty: (int) property fromHTML: (NSString *) fromHTML {
long color = HTMLtoLong(fromHTML);
if (color >= 0)
mBackend->WndProc(property, color, 0);
}
I did not write setColorProperty and do not like it and other similar methods (setGeneralProperty, setReferenceProperty, setLexerProperty... - the last 470 lines of ScintillaView.mm) as they are incomplete and inconsistent, assume UTF-8, and are not documented. They provide the hope of an API that follows Objective C conventions but doesn't really deliver so application code becomes a mix of these and more 'C-like' calls. They are an awkward part-way stage producing code like
[mEditor setGeneralProperty: SCI_SETLEXER parameter: SCLEX_MYSQL value: 0]
when a more ambitious wrapper would havemEditor.lexer = SCLEX_MYSQL
.The path I recommend is for applications to retrieve the 'direct function' (SCI_GETDIRECTFUNCTION + SCI_GETDIRECTPOINTER) and use that to call Scintilla APIs directly. If there is a desire for a more pleasant API then that should be constructed over the direct function.
If you really want to continue down this path then the changes can go in but I had rather hoped that these methods wouldn't be widely used.
I guess you're right. There is no point in polishing a turd. I will revert my local changes and just use the low level API.
OK, closing this issue.
In the long term, there may be some work towards a more friendly API wrapper for C++ but that won't match Objective C or Swift that well. The include/Scintilla.iface file can be used for creating language-friendly APIs either at run time for interpreted languages like Lua or by code generation.