mirror of https://github.com/buggins/dlangui.git
ascii-unicode improvements
This commit is contained in:
parent
f4d26fa758
commit
3ba090d4cb
|
@ -5,10 +5,11 @@ import std.conv : to;
|
||||||
import std.string;
|
import std.string;
|
||||||
import std.array : empty;
|
import std.array : empty;
|
||||||
import std.algorithm : equal;
|
import std.algorithm : equal;
|
||||||
import std.ascii : isAlpha;
|
import std.ascii : isAlpha, isWhite;
|
||||||
|
|
||||||
import dlangui.core.dom;
|
import dlangui.core.dom;
|
||||||
import dlangui.core.css;
|
import dlangui.core.css;
|
||||||
|
import dlangui.core.types : parseHexDigit;
|
||||||
|
|
||||||
/// skip specified count of chars of string, returns next available character, or 0 if end of string reached
|
/// skip specified count of chars of string, returns next available character, or 0 if end of string reached
|
||||||
private char skip(ref string src, int count = 1) {
|
private char skip(ref string src, int count = 1) {
|
||||||
|
@ -33,7 +34,7 @@ private char skipSpaces(ref string str)
|
||||||
char ch = str.peek;
|
char ch = str.peek;
|
||||||
if (!ch)
|
if (!ch)
|
||||||
return 0;
|
return 0;
|
||||||
while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
|
while (isWhite(ch))
|
||||||
ch = str.skip;
|
ch = str.skip;
|
||||||
if (str.peek == '/' && str.peek(1) == '*') {
|
if (str.peek == '/' && str.peek(1) == '*') {
|
||||||
// comment found
|
// comment found
|
||||||
|
@ -44,7 +45,7 @@ private char skipSpaces(ref string str)
|
||||||
str.skip(2);
|
str.skip(2);
|
||||||
}
|
}
|
||||||
ch = str.peek;
|
ch = str.peek;
|
||||||
while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')
|
while (isWhite(ch))
|
||||||
ch = str.skip;
|
ch = str.skip;
|
||||||
if (oldpos.ptr is str.ptr)
|
if (oldpos.ptr is str.ptr)
|
||||||
break;
|
break;
|
||||||
|
@ -57,7 +58,7 @@ private char skipSpaces(ref string str)
|
||||||
|
|
||||||
|
|
||||||
private bool isIdentChar(char ch) {
|
private bool isIdentChar(char ch) {
|
||||||
return (ch >= 'A' && ch <='Z') || (ch >= 'a' && ch <='z') || (ch == '-') || (ch == '_');
|
return isAlpha(ch) || (ch == '-') || (ch == '_');
|
||||||
}
|
}
|
||||||
|
|
||||||
/// parse css identifier
|
/// parse css identifier
|
||||||
|
@ -143,17 +144,6 @@ private bool nextProperty(ref string str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private int hexDigit( char c )
|
|
||||||
{
|
|
||||||
if ( c >= '0' && c <= '9' )
|
|
||||||
return c-'0';
|
|
||||||
if ( c >= 'A' && c <= 'F' )
|
|
||||||
return c - 'A' + 10;
|
|
||||||
if ( c >= 'a' && c <= 'f' )
|
|
||||||
return c - 'a' + 10;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int parseStandardColor(string ident) {
|
private int parseStandardColor(string ident) {
|
||||||
switch(ident) {
|
switch(ident) {
|
||||||
case "black": return 0x000000;
|
case "black": return 0x000000;
|
||||||
|
@ -205,23 +195,23 @@ private bool parseColor(ref string src, ref CssValue value)
|
||||||
// #rgb or #rrggbb colors
|
// #rgb or #rrggbb colors
|
||||||
ch = src.skip;
|
ch = src.skip;
|
||||||
int nDigits = 0;
|
int nDigits = 0;
|
||||||
for ( ; nDigits < src.length && hexDigit(src[nDigits])>=0; nDigits++ ) {
|
for ( ; nDigits < src.length && parseHexDigit(src[nDigits])>=0; nDigits++ ) {
|
||||||
}
|
}
|
||||||
if ( nDigits==3 ) {
|
if ( nDigits==3 ) {
|
||||||
int r = hexDigit( src[0] );
|
int r = parseHexDigit( src[0] );
|
||||||
int g = hexDigit( src[1] );
|
int g = parseHexDigit( src[1] );
|
||||||
int b = hexDigit( src[2] );
|
int b = parseHexDigit( src[2] );
|
||||||
value.type = CssValueType.color;
|
value.type = CssValueType.color;
|
||||||
value.value = (((r + r*16) * 256) | (g + g*16)) * 256 | (b + b*16);
|
value.value = (((r + r*16) * 256) | (g + g*16)) * 256 | (b + b*16);
|
||||||
src.skip(3);
|
src.skip(3);
|
||||||
return true;
|
return true;
|
||||||
} else if ( nDigits==6 ) {
|
} else if ( nDigits==6 ) {
|
||||||
int r = hexDigit( src[0] ) * 16;
|
int r = parseHexDigit( src[0] ) * 16;
|
||||||
r += hexDigit( src[1] );
|
r += parseHexDigit( src[1] );
|
||||||
int g = hexDigit( src[2] ) * 16;
|
int g = parseHexDigit( src[2] ) * 16;
|
||||||
g += hexDigit( src[3] );
|
g += parseHexDigit( src[3] );
|
||||||
int b = hexDigit( src[4] ) * 16;
|
int b = parseHexDigit( src[4] ) * 16;
|
||||||
b += hexDigit( src[5] );
|
b += parseHexDigit( src[5] );
|
||||||
value.type = CssValueType.color;
|
value.type = CssValueType.color;
|
||||||
value.value = ((r * 256) | g) * 256 | b;
|
value.value = ((r * 256) | g) * 256 | b;
|
||||||
src.skip(6);
|
src.skip(6);
|
||||||
|
|
|
@ -626,9 +626,7 @@ class EditableContent {
|
||||||
performOperation(op, this);
|
performOperation(op, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isAlphaForWordSelection(dchar ch) {
|
static alias isAlphaForWordSelection = isAlNum;
|
||||||
return ch == '_' || (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
|
|
||||||
}
|
|
||||||
|
|
||||||
/// get word bounds by position
|
/// get word bounds by position
|
||||||
TextRange wordBounds(TextPosition pos) {
|
TextRange wordBounds(TextPosition pos) {
|
||||||
|
@ -1133,21 +1131,18 @@ class EditableContent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isDigit(dchar ch) pure nothrow {
|
|
||||||
return ch >= '0' && ch <= '9';
|
static alias isDigit = std.uni.isNumber;
|
||||||
}
|
|
||||||
static bool isAlpha(dchar ch) pure nothrow {
|
static bool isAlpha(dchar ch) pure nothrow {
|
||||||
return isLowerAlpha(ch) || isUpperAlpha(ch);
|
return std.uni.isAlpha(ch) || ch == '_';
|
||||||
}
|
}
|
||||||
static bool isAlNum(dchar ch) pure nothrow {
|
static bool isAlNum(dchar ch) pure nothrow {
|
||||||
return isDigit(ch) || isAlpha(ch);
|
return isDigit(ch) || isAlpha(ch);
|
||||||
}
|
}
|
||||||
static bool isLowerAlpha(dchar ch) pure nothrow {
|
static bool isLowerAlpha(dchar ch) pure nothrow {
|
||||||
return (ch >= 'a' && ch <= 'z') || (ch == '_');
|
return std.uni.isLower(ch) || ch == '_';
|
||||||
}
|
|
||||||
static bool isUpperAlpha(dchar ch) pure nothrow {
|
|
||||||
return (ch >= 'A' && ch <= 'Z');
|
|
||||||
}
|
}
|
||||||
|
static alias isUpperAlpha = std.uni.isUpper;
|
||||||
static bool isPunct(dchar ch) pure nothrow {
|
static bool isPunct(dchar ch) pure nothrow {
|
||||||
switch(ch) {
|
switch(ch) {
|
||||||
case '.':
|
case '.':
|
||||||
|
|
|
@ -27,6 +27,7 @@ Authors: Vadim Lopatin, coolreader.org@gmail.com
|
||||||
module dlangui.core.settings;
|
module dlangui.core.settings;
|
||||||
|
|
||||||
import dlangui.core.logger;
|
import dlangui.core.logger;
|
||||||
|
import dlangui.core.types : parseHexDigit;
|
||||||
import std.range;
|
import std.range;
|
||||||
import std.algorithm : equal;
|
import std.algorithm : equal;
|
||||||
import std.conv : to;
|
import std.conv : to;
|
||||||
|
@ -1623,42 +1624,28 @@ final class Setting {
|
||||||
context = "near `" ~ json[contextStart .. contextEnd] ~ "` ";
|
context = "near `" ~ json[contextStart .. contextEnd] ~ "` ";
|
||||||
throw new Exception("JSON parsing error in (" ~ to!string(line) ~ ":" ~ to!string(col) ~ ") " ~ context ~ ": " ~ msg);
|
throw new Exception("JSON parsing error in (" ~ to!string(line) ~ ":" ~ to!string(col) ~ ") " ~ context ~ ": " ~ msg);
|
||||||
}
|
}
|
||||||
static bool isSpace(char ch) {
|
|
||||||
return ch== ' ' || ch == '\t' || ch == '\r' || ch == '\n';
|
|
||||||
}
|
|
||||||
static bool isAlpha(char ch) {
|
static bool isAlpha(char ch) {
|
||||||
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_';
|
return std.ascii.isAlpha(ch) || ch == '_';
|
||||||
}
|
}
|
||||||
static bool isAlNum(char ch) {
|
static bool isAlNum(char ch) {
|
||||||
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_';
|
return std.ascii.isAlphaNum(ch) || ch == '_';
|
||||||
}
|
|
||||||
static bool isDigit(char ch) {
|
|
||||||
return (ch >= '0' && ch <= '9');
|
|
||||||
}
|
}
|
||||||
@property char skipSpaces() {
|
@property char skipSpaces() {
|
||||||
for(;pos < json.length;pos++) {
|
for(;pos < json.length;pos++) {
|
||||||
char ch = json[pos];
|
char ch = json[pos];
|
||||||
if (!isSpace(ch))
|
if (!std.ascii.isWhite(ch))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return peek;
|
return peek;
|
||||||
}
|
}
|
||||||
static int parseHexDigit(char ch) {
|
|
||||||
if (ch >= '0' && ch <='9')
|
|
||||||
return ch - '0';
|
|
||||||
if (ch >= 'a' && ch <='f')
|
|
||||||
return ch - 'a' + 10;
|
|
||||||
if (ch >= 'A' && ch <='F')
|
|
||||||
return ch - 'A' + 10;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
string parseUnicodeChar() {
|
string parseUnicodeChar() {
|
||||||
if (pos >= json.length - 3)
|
if (pos >= json.length - 3)
|
||||||
error("unexpected end of file while parsing unicode character entity inside string");
|
error("unexpected end of file while parsing unicode character entity inside string");
|
||||||
dchar ch = 0;
|
dchar ch = 0;
|
||||||
foreach(i; 0 .. 4) {
|
foreach(i; 0 .. 4) {
|
||||||
int d = parseHexDigit(nextChar);
|
uint d = parseHexDigit(nextChar);
|
||||||
if (d < 0)
|
if (d == uint.max)
|
||||||
error("error while parsing unicode character entity inside string");
|
error("error while parsing unicode character entity inside string");
|
||||||
ch = (ch << 4) | d;
|
ch = (ch << 4) | d;
|
||||||
}
|
}
|
||||||
|
@ -1756,6 +1743,7 @@ final class Setting {
|
||||||
|
|
||||||
// parse long, ulong or double
|
// parse long, ulong or double
|
||||||
void parseNumber(Setting res) {
|
void parseNumber(Setting res) {
|
||||||
|
import std.ascii : isDigit;
|
||||||
char ch = peek;
|
char ch = peek;
|
||||||
int sign = 1;
|
int sign = 1;
|
||||||
if (ch == '-') {
|
if (ch == '-') {
|
||||||
|
@ -1886,7 +1874,7 @@ final class Setting {
|
||||||
this = true;
|
this = true;
|
||||||
} else if (parser.parseKeyword("false")) {
|
} else if (parser.parseKeyword("false")) {
|
||||||
this = false;
|
this = false;
|
||||||
} else if (ch == '-' || JsonParser.isDigit(ch)) {
|
} else if (ch == '-' || std.ascii.isDigit(ch)) {
|
||||||
parser.parseNumber(this);
|
parser.parseNumber(this);
|
||||||
} else {
|
} else {
|
||||||
parser.error("cannot parse JSON value");
|
parser.error("cannot parse JSON value");
|
||||||
|
|
|
@ -45,19 +45,13 @@ public import dlangui.core.config;
|
||||||
|
|
||||||
import std.algorithm;
|
import std.algorithm;
|
||||||
|
|
||||||
/** 2D point */
|
/// 2D point
|
||||||
struct Point {
|
struct Point {
|
||||||
/// x coordinate
|
|
||||||
int x;
|
int x;
|
||||||
/// y coordinate
|
|
||||||
int y;
|
int y;
|
||||||
this(int x0, int y0) {
|
|
||||||
x = x0;
|
|
||||||
y = y0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 2D rectangle */
|
/// 2D rectangle
|
||||||
struct Rect {
|
struct Rect {
|
||||||
/// x coordinate of top left corner
|
/// x coordinate of top left corner
|
||||||
int left;
|
int left;
|
||||||
|
@ -427,26 +421,6 @@ struct Ref(T) { // if (T is RefCountedObject)
|
||||||
//================================================================================
|
//================================================================================
|
||||||
// some utility functions
|
// some utility functions
|
||||||
|
|
||||||
/*
|
|
||||||
string fromStringz(const(char[]) s) {
|
|
||||||
if (s is null)
|
|
||||||
return null;
|
|
||||||
int i = 0;
|
|
||||||
while(s[i])
|
|
||||||
i++;
|
|
||||||
return cast(string)(s[0..i].dup);
|
|
||||||
}
|
|
||||||
|
|
||||||
string fromStringz(const(char*) s) {
|
|
||||||
if (s is null)
|
|
||||||
return null;
|
|
||||||
int i = 0;
|
|
||||||
while(s[i])
|
|
||||||
i++;
|
|
||||||
return cast(string)(s[0..i].dup);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** conversion from wchar z-string */
|
/** conversion from wchar z-string */
|
||||||
wstring fromWStringz(const(wchar[]) s) {
|
wstring fromWStringz(const(wchar[]) s) {
|
||||||
if (s is null)
|
if (s is null)
|
||||||
|
@ -497,15 +471,20 @@ enum State : uint {
|
||||||
Parent = 0x10000, // use parent's state
|
Parent = 0x10000, // use parent's state
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Deprecated: use std.uni.toUpper instead.
|
||||||
Uppercase unicode character.
|
Uppercase unicode character.
|
||||||
|
|
||||||
TODO: support non-ascii.
|
|
||||||
*/
|
*/
|
||||||
dchar dcharToUpper(dchar ch) {
|
deprecated dchar dcharToUpper(dchar ch) {
|
||||||
// TODO: support non-ascii letters
|
return std.uni.toUpper(ch);
|
||||||
if (ch >= 'a' && ch <= 'z')
|
|
||||||
return ch - 'a' + 'A';
|
|
||||||
return ch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// decodes hex digit (0..9, a..f, A..F), returns uint.max if invalid
|
||||||
|
uint parseHexDigit(T)(T ch) pure nothrow {
|
||||||
|
if (ch >= '0' && ch <= '9')
|
||||||
|
return ch - '0';
|
||||||
|
else if (ch >= 'a' && ch <= 'f')
|
||||||
|
return ch - 'a' + 10;
|
||||||
|
else if (ch >= 'A' && ch <= 'F')
|
||||||
|
return ch - 'A' + 10;
|
||||||
|
return uint.max;
|
||||||
|
}
|
||||||
|
|
|
@ -347,13 +347,13 @@ class Tokenizer {
|
||||||
foreach(i; 0 .. prefixLen)
|
foreach(i; 0 .. prefixLen)
|
||||||
ch = skipChar();
|
ch = skipChar();
|
||||||
|
|
||||||
uint n = decodeHexDigit(ch);
|
uint n = parseHexDigit(ch);
|
||||||
if (n == uint.max)
|
if (n == uint.max)
|
||||||
return parseError();
|
return parseError();
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
ch = skipChar();
|
ch = skipChar();
|
||||||
uint digit = decodeHexDigit(ch);
|
uint digit = parseHexDigit(ch);
|
||||||
if (digit == uint.max)
|
if (digit == uint.max)
|
||||||
break;
|
break;
|
||||||
n = (n << 4) + digit;
|
n = (n << 4) + digit;
|
||||||
|
|
|
@ -163,17 +163,6 @@ bool isFullyTransparentColor(uint color) pure nothrow {
|
||||||
return (color >> 24) == 0xFF;
|
return (color >> 24) == 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// decodes hex digit (0..9, a..f, A..F), returns uint.max if invalid
|
|
||||||
uint decodeHexDigit(T)(T ch) pure nothrow {
|
|
||||||
if (ch >= '0' && ch <= '9')
|
|
||||||
return ch - '0';
|
|
||||||
else if (ch >= 'a' && ch <= 'f')
|
|
||||||
return ch - 'a' + 10;
|
|
||||||
else if (ch >= 'A' && ch <= 'F')
|
|
||||||
return ch - 'A' + 10;
|
|
||||||
return uint.max;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// decode color string supported formats: #RGB #ARGB #RRGGBB #AARRGGBB
|
/// decode color string supported formats: #RGB #ARGB #RRGGBB #AARRGGBB
|
||||||
uint decodeHexColor(string s, uint defValue = 0) pure {
|
uint decodeHexColor(string s, uint defValue = 0) pure {
|
||||||
s = strip(s);
|
s = strip(s);
|
||||||
|
@ -205,7 +194,7 @@ uint decodeHexColor(string s, uint defValue = 0) pure {
|
||||||
return defValue;
|
return defValue;
|
||||||
uint value = 0;
|
uint value = 0;
|
||||||
foreach(i; 1 .. s.length) {
|
foreach(i; 1 .. s.length) {
|
||||||
uint digit = decodeHexDigit(s[i]);
|
uint digit = parseHexDigit(s[i]);
|
||||||
if (digit == uint.max)
|
if (digit == uint.max)
|
||||||
return defValue;
|
return defValue;
|
||||||
value = (value << 4) | digit;
|
value = (value << 4) | digit;
|
||||||
|
|
|
@ -7,7 +7,7 @@ Layouts are similar to the same in Android.
|
||||||
|
|
||||||
LinearLayout - either VerticalLayout or HorizontalLayout.
|
LinearLayout - either VerticalLayout or HorizontalLayout.
|
||||||
VerticalLayout - just LinearLayout with orientation=Orientation.Vertical
|
VerticalLayout - just LinearLayout with orientation=Orientation.Vertical
|
||||||
HorizontalLayout - just LinearLayout with orientation=Orientation.Vertical
|
HorizontalLayout - just LinearLayout with orientation=Orientation.Horizontal
|
||||||
FrameLayout - children occupy the same place, usually one one is visible at a time
|
FrameLayout - children occupy the same place, usually one one is visible at a time
|
||||||
TableLayout - children aligned into rows and columns
|
TableLayout - children aligned into rows and columns
|
||||||
ResizerWidget - widget to resize sibling widgets
|
ResizerWidget - widget to resize sibling widgets
|
||||||
|
|
|
@ -155,14 +155,14 @@ class MenuItem {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dcharToUpper(ch);
|
return std.uni.toUpper(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// find subitem by hotkey character, returns subitem index, -1 if not found
|
/// find subitem by hotkey character, returns subitem index, -1 if not found
|
||||||
int findSubitemByHotkey(dchar ch) {
|
int findSubitemByHotkey(dchar ch) {
|
||||||
if (!ch)
|
if (!ch)
|
||||||
return -1;
|
return -1;
|
||||||
ch = dcharToUpper(ch);
|
ch = std.uni.toUpper(ch);
|
||||||
for (int i = 0; i < _subitems.length; i++) {
|
for (int i = 0; i < _subitems.length; i++) {
|
||||||
if (_subitems[i].getHotkey() == ch)
|
if (_subitems[i].getHotkey() == ch)
|
||||||
return i;
|
return i;
|
||||||
|
|
Loading…
Reference in New Issue