diff options
Diffstat (limited to 'src/unicoderange.cpp')
-rw-r--r-- | src/unicoderange.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/unicoderange.cpp b/src/unicoderange.cpp new file mode 100644 index 0000000..237fac7 --- /dev/null +++ b/src/unicoderange.cpp @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * TODO: insert short description here + *//* + * Authors: see git history + * + * Copyright (C) 2018 Authors + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ +#include "unicoderange.h" + +#include <cstdlib> +#include <cstring> + +static unsigned int hex2int(char* s){ + int res=0; + int i=0, mul=1; + while(s[i+1]!='\0') i++; + + while(i>=0){ + if (s[i] >= 'A' && s[i] <= 'F') res += mul * (s[i]-'A'+10); + if (s[i] >= 'a' && s[i] <= 'f') res += mul * (s[i]-'a'+10); + if (s[i] >= '0' && s[i] <= '9') res += mul * (s[i]-'0'); + i--; + mul*=16; + } + return res; +} + +UnicodeRange::UnicodeRange(const gchar* value){ + if (!value) return; + gchar* val = (gchar*) value; + while(val[0] != '\0'){ + if (val[0]=='U' && val[1]=='+'){ + val += add_range(val+2); + } else { + this->unichars.push_back(g_utf8_get_char(&val[0])); + val = g_utf8_next_char(val); + } + //skip spaces or commas + while(val[0]==' ' || val[0]==',') val++; + } +} + +int UnicodeRange::add_range(gchar* val){ + Urange r; + int i=0, count=0; + while(val[i]!='\0' && val[i]!='-' && val[i]!=' ' && val[i]!=','){ + i++; + } + r.start = (gchar*) malloc((i+1)*sizeof(gchar)); + strncpy(r.start, val, i); + r.start[i] = '\0'; + val+=i; + count+=i; + i=0; + if (val[0]=='-'){ + val++; + while(val[i]!='\0' && val[i]!='-' && val[i]!=' ' && val[i]!=',') i++; + r.end = (gchar*) malloc((i+1)*sizeof(gchar)); + strncpy(r.end, val, i); + r.end[i] = '\0'; + // val+=i; + count+=i; + } else { + r.end=nullptr; + } + this->range.push_back(r); + return count+1; +} + +bool UnicodeRange::contains(gchar unicode){ + for(unsigned int unichar : this->unichars){ + if (static_cast<gunichar>(unicode) == unichar){ + return true; + } + } + + unsigned int unival; + unival = g_utf8_get_char (&unicode); + char uni[9] = "00000000"; + uni[8]= '\0'; + for (unsigned int i=7; unival>0; i--){ + unsigned char val = unival & 0xf; + unival = unival >> 4; + if (val < 10) uni[i] = '0' + val; + else uni[i] = 'A'+ val - 10; + } + + bool found; + for(auto r : this->range){ + if (r.end){ + if (unival >= hex2int(r.start) && unival <= hex2int(r.end)) return true; + } else { + found = true; + + int p=0; + while (r.start[p]!='\0') p++; + p--; + + for (int pos=8;p>=0;pos--,p--){ + if (uni[pos]!='?' && uni[pos]!=r.start[p]) found = false; + } + if (found) return true; + } + } + return false; +} + +Glib::ustring UnicodeRange::attribute_string(){ + Glib::ustring result; + unsigned int i; + for(i=0; i<this->unichars.size(); i++){ +// g_warning("uni: %d %x", i, unichars[i]); + result += this->unichars[i]; + if (i!=this->unichars.size()-1) result += ","; + } + + for(i=0; i<this->range.size(); i++){ + result += "U+" + Glib::ustring(this->range[i].start); + if (this->range[i].end) result += "-" + Glib::ustring(this->range[i].end); + if (i!=this->range.size()-1) result += ", "; + } + + return result; +} + +gunichar UnicodeRange::sample_glyph(){ + //This could be better + if (!unichars.empty()) + return unichars[0]; + if (!range.empty()) + return hex2int(range[0].start); + return (gunichar) ' '; +} + |