CharDatabase.vala
/*
Copyright (C) 2012 2015 Johan Mattsson
All rights reserved.
*/
using Gee;
using Sqlite;
namespace BirdFont {
public class CharDatabase {
public static GlyphRange full_unicode_range;
static unowned Database db;
static Database? database = null;
public CharDatabase () {
File f;
full_unicode_range = new GlyphRange ();
f = get_database_file ();
open_database () ;
}
public static void open_database () {
File f = get_database_file ();
printd (@"Open database: " + (!) f.get_path () + "\n");
int rc = Database.open_v2 ((!) f.get_path (), out database, OPEN_READONLY);
db = (!) database;
if (rc != Sqlite.OK) {
stderr.printf ("Can't open database: %d, %s\n", rc, db.errmsg ());
}
}
public static File get_database_file () {
return SearchPaths.find_file (null, "ucd.sqlite");
}
public static GlyphRange search (string s) {
GlyphRange result = new GlyphRange ();
GlyphRange ucd_result = new GlyphRange ();
int rc, cols;
Statement statement;
string select;
unichar c;
string query = s.strip ();
if (query.has_prefix ("U+") || query.has_prefix ("u+")) {
c = Font.to_unichar (query.down ());
if (c != '\0') {
result.add_single (c);
}
}
if (query.char_count () == 1) {
result.add_single (s.get_char (0));
}
string[] terms = query.split (" ");
bool first = true;
select = "";
foreach (string term in terms) {
if (first) {
select = "SELECT unicode FROM Words "
+ "WHERE word GLOB '" + term.replace ("'", "''") + "' ";
} else {
select += "OR word GLOB '" + term.replace ("'", "''") + "' ";
}
first = false;
}
select += ";";
rc = db.prepare_v2 (select, select.length, out statement, null);
if (rc == Sqlite.OK) {
cols = statement.column_count();
if (cols != 1) {
warning ("Expecting one column.");
return result;
}
while (true) {
rc = statement.step ();
if (rc == Sqlite.DONE) {
break;
} else if (rc == Sqlite.ROW) {
c = (unichar) statement.column_int64 (0);
if (has_all_terms (c, query)) {
ucd_result.add_single (c);
}
} else {
warning ("Error: %d, %s\n", rc, db.errmsg ());
break;
}
}
try {
if (ucd_result.get_length () > 0) {
ucd_result.sort ();
result.parse_ranges (ucd_result.get_all_ranges ());
}
} catch (MarkupError e) {
warning (e.message);
}
} else {
warning ("SQL error: %d, %s\n", rc, db.errmsg ());
}
return result;
}
public static bool has_ascender (unichar c) {
if (!c.islower()) return true;
switch (c) {
case 'b': return true;
case 'd': return true;
case 'f': return true;
case 'h': return true;
case 'k': return true;
case 'l': return true;
}
return false;
}
public static bool has_descender (unichar c) {
switch (c) {
case 'g': return true;
case 'j': return true;
case 'p': return true;
case 'q': return true;
case 'y': return true;
}
return false;
}
static bool has_term (unichar c, string term) {
Statement statement;
string select = "SELECT unicode FROM Words "
+ "WHERE word GLOB '" + term.replace ("'", "''") + "' "
+ @"AND unicode = $((int64) c);";
int rc = db.prepare_v2 (select, select.length, out statement, null);
if (rc == Sqlite.OK) {
rc = statement.step ();
if (rc == Sqlite.DONE) {
return false;
} else if (rc == Sqlite.ROW) {
c = (unichar) statement.column_int64 (0);
return true;
}
} else {
warning ("Error: %d, %s\n", rc, db.errmsg ());
return false;
}
return false;
}
static bool has_all_terms (unichar c, string query) {
string[] terms = query.split (" ");
foreach (string term in terms) {
if (!has_term (c, term)) {
return false;
}
}
return true;
}
public static string get_unicode_database_entry (unichar c) {
string description = "";
int rc, cols;
Statement statement;
string select = "SELECT description FROM Description "
+ @"WHERE unicode = $((int64) c)";
rc = db.prepare_v2 (select, select.length, out statement, null);
if (rc == Sqlite.OK) {
cols = statement.column_count();
if (cols != 1) {
warning ("Expecting one column.");
return description;
}
while (true) {
rc = statement.step ();
if (rc == Sqlite.DONE) {
break;
} else if (rc == Sqlite.ROW) {
description = statement.column_text (0);
} else {
printerr ("Error: %d, %s\n", rc, db.errmsg ());
break;
}
}
} else {
printerr ("SQL error: %d, %s\n", rc, db.errmsg ());
}
if (description == "") {
description = Font.to_hex (c).replace ("U+", "") + "\tUNICODE CHARACTER";
}
return description;
}
public static void get_full_unicode (GlyphRange glyph_range) {
try {
if (!is_null (full_unicode_range)) {
glyph_range.parse_ranges (full_unicode_range.get_all_ranges ());
}
} catch (MarkupError e) {
warning (e.message);
}
}
}
}