mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
RichEdit related: MakeSpellScd utility to create .scd spelling checker files, also fixed RichEdit to support UTF-8 based format
git-svn-id: svn://ultimatepp.org/upp/trunk@1673 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
b3846831ff
commit
9fb35c2ca3
6 changed files with 300 additions and 27 deletions
|
|
@ -2786,7 +2786,6 @@ void ToAscii(char *s, int len, byte charset)
|
|||
ToAscii(s, s, len, charset);
|
||||
}
|
||||
|
||||
|
||||
WString ToUnicode(const char *src, int l, byte charset)
|
||||
{
|
||||
charset = ResolveCharset(charset);
|
||||
|
|
@ -2802,17 +2801,21 @@ WString ToUnicode(const String& src, byte charset)
|
|||
return ToUnicode(src, src.GetLength(), charset);
|
||||
}
|
||||
|
||||
String FromUnicode(const WString& src, byte charset, int def)
|
||||
String FromUnicodeBuffer(const wchar *src, int len, byte charset, int defchar)
|
||||
{
|
||||
charset = ResolveCharset(charset);
|
||||
if(charset == CHARSET_UTF8)
|
||||
return ToUtf8(src);
|
||||
int l = src.GetLength();
|
||||
StringBuffer result(l);
|
||||
FromUnicode(result, src, l, charset, def);
|
||||
return ToUtf8(src, len);
|
||||
StringBuffer result(len);
|
||||
FromUnicode(result, src, len, charset, defchar);
|
||||
return result;
|
||||
}
|
||||
|
||||
String FromUnicode(const WString& src, byte charset, int defchar)
|
||||
{
|
||||
return FromUnicodeBuffer(~src, src.GetCount(), charset, defchar);
|
||||
}
|
||||
|
||||
String ToCharset(byte charset, const String& src, byte scharset, int def)
|
||||
{
|
||||
charset = ResolveCharset(charset);
|
||||
|
|
|
|||
|
|
@ -268,6 +268,7 @@ bool CheckUtf8(const String& src);
|
|||
|
||||
WString ToUnicode(const String& src, byte charset);
|
||||
WString ToUnicode(const char *src, int n, byte charset);
|
||||
String FromUnicodeBuffer(const wchar *src, int len, byte charset = CHARSET_DEFAULT, int defchar = DEFAULTCHAR);
|
||||
String FromUnicode(const WString& src, byte charset = CHARSET_DEFAULT, int defchar = DEFAULTCHAR);
|
||||
|
||||
String ToCharset(byte charset, const String& s, byte scharset = CHARSET_DEFAULT, int defchar = DEFAULTCHAR);
|
||||
|
|
|
|||
234
uppsrc/MakeSpellScd/MakeSpellScd.cpp
Normal file
234
uppsrc/MakeSpellScd/MakeSpellScd.cpp
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
#include <Core/Core.h>
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
#define LLOGHEXDUMP(a, b) // LOGHEXDUMP(a, b)
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
byte charset;
|
||||
int vocn[256];
|
||||
Vector<String> voc;
|
||||
VectorMap<int, String> line;
|
||||
|
||||
int LineCode(const String& us)
|
||||
{
|
||||
WString s = FromUtf8(us);
|
||||
return ToLower(ToAscii(s[0]), CHARSET_DEFAULT) +
|
||||
(ToLower(ToAscii(s[1]), CHARSET_DEFAULT) << 8) +
|
||||
(s.GetCount() < 3 ? 127 : (ToLower(ToAscii(s[2]), CHARSET_DEFAULT) << 16));
|
||||
}
|
||||
|
||||
bool Contains(const String& a, const String& b)
|
||||
{
|
||||
for(int i = 0; i + b.GetLength() <= a.GetLength(); i++)
|
||||
if(memcmp(~a + i, ~b, b.GetLength()) == 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
struct LengthOrder
|
||||
{
|
||||
bool operator()(const String& a, const String& b) const
|
||||
{
|
||||
return a.GetLength() > b.GetLength();
|
||||
}
|
||||
};
|
||||
|
||||
struct NoCaseOrder
|
||||
{
|
||||
bool operator()(const String& a, const String& b) const
|
||||
{
|
||||
String la = ToAscii(a);
|
||||
String lb = ToAscii(b);
|
||||
int q = SgnCompare(ToLower(ToAscii(a)), ToLower(ToAscii(b)));
|
||||
if(q)
|
||||
return q < 0;
|
||||
q = SgnCompare(ToLower(a), ToLower(b));
|
||||
if(q)
|
||||
return q < 0;
|
||||
return a < b;
|
||||
}
|
||||
};
|
||||
|
||||
void Make()
|
||||
{
|
||||
FileIn in(CommandLine()[0]);
|
||||
if(!in) {
|
||||
Cout() << "Unable to open " << CommandLine()[0] << " for reading\n";
|
||||
SetExitCode(1);
|
||||
return;
|
||||
}
|
||||
FileOut out(CommandLine()[1]);
|
||||
if(!out) {
|
||||
Cout() << "Unable to open " << CommandLine()[1] << " for writing\n";
|
||||
SetExitCode(1);
|
||||
return;
|
||||
}
|
||||
SetDefaultCharset(CHARSET_UTF8);
|
||||
Vector<String> w;
|
||||
Index<int> alphabet;
|
||||
String maxl;
|
||||
int maxlen = 0;
|
||||
while(!in.IsEof()) {
|
||||
String l = in.GetLine();
|
||||
if(l.GetLength() > maxlen) {
|
||||
maxlen = l.GetLength();
|
||||
maxl = l;
|
||||
}
|
||||
if(FromUtf8(l).GetLength() > 1) {
|
||||
w.Add(l);
|
||||
for(const char *s = l; s < l.End(); s++)
|
||||
alphabet.FindAdd((byte)*s);
|
||||
}
|
||||
}
|
||||
|
||||
if(alphabet.GetCount() > 250) {
|
||||
Cout() << "Alphabet is too big - only 250 different codepoints allowed.";
|
||||
SetExitCode(1);
|
||||
return;
|
||||
}
|
||||
|
||||
Cout() << "Words loaded, now sorting\n";
|
||||
|
||||
ASSERT(maxlen < 64);
|
||||
|
||||
LLOG("Maximal length:" << maxlen << " " << maxl);
|
||||
|
||||
Sort(w, NoCaseOrder());
|
||||
|
||||
Cout() << "Sorted, now gathering voc candidates\n";
|
||||
|
||||
// ------------------
|
||||
|
||||
VectorMap<String, int> part;
|
||||
int dict = 0;
|
||||
int i = 0;
|
||||
while(i < w.GetCount()) {
|
||||
int linecode = LineCode(w[i]);
|
||||
String prevw;
|
||||
LLOG("line " << ~ToLower(w[i].Mid(0, 3)));
|
||||
while(i < w.GetCount() && LineCode(w[i]) == linecode) {
|
||||
String ww = w[i];
|
||||
int j;
|
||||
for(j = 0; j < prevw.GetLength(); j++)
|
||||
if(ww[j] != prevw[j]) break;
|
||||
if(j >= dict)
|
||||
dict = j + 1;
|
||||
for(int l = 2; l < ww.GetLength() - 1; l++)
|
||||
for(int q = j; q + l <= ww.GetLength(); q++)
|
||||
part.GetAdd(ww.Mid(q, l), 0)++;
|
||||
prevw = ww;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
Cout() << "Creating voc\n";
|
||||
|
||||
int dcount = 256 - dict;
|
||||
LLOG("dict: " << dict);
|
||||
LLOG("dict size: " << dcount);
|
||||
LLOG(" alphabet:" << alphabet.GetCount());
|
||||
LLOG(" combinations: " << dcount - alphabet.GetCount());
|
||||
|
||||
for(i = 0; i < alphabet.GetCount(); i++)
|
||||
voc.Add(String(alphabet[i], 1));
|
||||
|
||||
Vector<int> value;
|
||||
|
||||
for(i = 0; i < part.GetCount(); i++)
|
||||
value.Add() = part[i] * (part.GetKey(i).GetLength() - 1);
|
||||
|
||||
while(voc.GetCount() + dict < 256) {
|
||||
int m = 0;
|
||||
int mi = 0;
|
||||
int i;
|
||||
for(i = 0; i < part.GetCount(); i++)
|
||||
if(value[i] > m) {
|
||||
m = value[i];
|
||||
mi = i;
|
||||
}
|
||||
if(m <= 0) break;
|
||||
String v = part.GetKey(mi);
|
||||
vocn[voc.GetCount()] = value[mi];
|
||||
voc.Add(v);
|
||||
LLOG("Adding " << v << " [" << v.GetCount() << "] value:" << value[mi] << " count:" << part[mi]);
|
||||
for(i = 0; i < part.GetCount(); i++) {
|
||||
if(Contains(part.GetKey(i), v))
|
||||
value[i] -= v.GetLength() * part[i];
|
||||
if(Contains(v, part.GetKey(i)))
|
||||
value[i] -= part.GetKey(i).GetLength() * part[i];
|
||||
}
|
||||
value[mi] = 0;
|
||||
}
|
||||
|
||||
int sum = 0;
|
||||
for(i = 0; i < voc.GetCount(); i++) {
|
||||
sum += vocn[i];
|
||||
LLOG(vocn[i] << " " << voc[i]);
|
||||
}
|
||||
LLOG("Total " << sum);
|
||||
|
||||
// ------------------
|
||||
Sort(voc, LengthOrder());
|
||||
|
||||
i = 0;
|
||||
while(i < w.GetCount()) {
|
||||
int linecode = LineCode(w[i]);
|
||||
String& ln = line.GetAdd(linecode);
|
||||
LLOG("---- Line " << ToLower(ToAscii(~w[i].Mid(0, 3))));
|
||||
String prevw;
|
||||
bool next = false;
|
||||
while(i < w.GetCount() && LineCode(w[i]) == linecode) {
|
||||
String ww = w[i];
|
||||
int j;
|
||||
for(j = 0; j < prevw.GetLength(); j++)
|
||||
if(ww[j] != prevw[j]) break;
|
||||
if(next)
|
||||
ln.Cat(j);
|
||||
LLOG(j << "\t" << w[i]);
|
||||
next = true;
|
||||
const char *s = ~ww + j;
|
||||
while(*s) {
|
||||
int i;
|
||||
for(i = 0; i < voc.GetCount(); i++) {
|
||||
if(memcmp(s, voc[i], voc[i].GetLength()) == 0) {
|
||||
LLOG(" " << s << " " << voc[i]);
|
||||
ln.Cat(i + dict);
|
||||
s += voc[i].GetLength();
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(i < voc.GetCount());
|
||||
}
|
||||
prevw = ww;
|
||||
i++;
|
||||
}
|
||||
LLOGHEXDUMP(~ln, ln.GetCount());
|
||||
}
|
||||
int l = 0;
|
||||
for(i = 0; i < line.GetCount(); i++) {
|
||||
line[i].Cat(0);
|
||||
l += line[i].GetLength();
|
||||
}
|
||||
out.Put(CHARSET_UTF8);
|
||||
out.Put(0);
|
||||
out.Put(dict);
|
||||
for(i = 0; i < voc.GetCount(); i++) {
|
||||
out.Put(voc[i]);
|
||||
out.Put(0);
|
||||
}
|
||||
for(i = 0; i < line.GetCount(); i++) {
|
||||
out.PutL(line.GetKey(i));
|
||||
out.PutL(line[i].GetLength());
|
||||
out.Put(line[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CONSOLE_APP_MAIN
|
||||
{
|
||||
if(CommandLine().GetCount() != 2) {
|
||||
Cout() << "Usage: MakeSpellScd <inputfile> <outputfile>\n";
|
||||
exit(1);
|
||||
}
|
||||
Make();
|
||||
Cout() << "* Finished\n";
|
||||
}
|
||||
13
uppsrc/MakeSpellScd/MakeSpellScd.upp
Normal file
13
uppsrc/MakeSpellScd/MakeSpellScd.upp
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
description "Utility for creation of RichEdit spelling dictionary files (.scd)\377";
|
||||
|
||||
optimize_speed;
|
||||
|
||||
uses
|
||||
Core;
|
||||
|
||||
file
|
||||
MakeSpellScd.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "";
|
||||
|
||||
4
uppsrc/MakeSpellScd/init
Normal file
4
uppsrc/MakeSpellScd/init
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef _MakeSpellScd_icpp_init_stub
|
||||
#define _MakeSpellScd_icpp_init_stub
|
||||
#include "Core/init"
|
||||
#endif
|
||||
|
|
@ -86,39 +86,57 @@ bool Speller::Check(const wchar *wrd, int wlen) const
|
|||
while(ws < we)
|
||||
*wt++ = ToLower(*ws++);
|
||||
|
||||
char w[64];
|
||||
char wl[64];
|
||||
FromUnicode(w, wrd, len, charset);
|
||||
FromUnicode(wl, wh, len, charset);
|
||||
if(len == 2) {
|
||||
w[len] = 127;
|
||||
wl[len++] = 127;
|
||||
const char *w;
|
||||
const char *wl;
|
||||
int i;
|
||||
int l2;
|
||||
if(charset == CHARSET_UTF8) {
|
||||
String wb = ToUtf8(wrd, len);
|
||||
w = wb;
|
||||
String wlb = ToUtf8(wh, len);
|
||||
wl = wlb;
|
||||
i = line.Find(ToLower(ToAscii(wrd[0]), charset) +
|
||||
(ToLower(ToAscii(wrd[1]), charset) << 8) +
|
||||
(wlen == 2 ? 127 : ToLower(ToAscii(wrd[2]), charset) << 16));
|
||||
len = wb.GetCount();
|
||||
l2 = wlb.GetCount();
|
||||
}
|
||||
else {
|
||||
char wb[64];
|
||||
FromUnicode(wb, wrd, len, charset);
|
||||
w = wb;
|
||||
char wlb[64];
|
||||
FromUnicode(wlb, wh, len, charset);
|
||||
wl = wlb;
|
||||
if(len == 2) {
|
||||
wb[len] = 127;
|
||||
wlb[len++] = 127;
|
||||
}
|
||||
i = line.Find(ToLower(wl[0], charset) +
|
||||
(ToLower(wl[1], charset) << 8) +
|
||||
(ToLower(wl[2], charset) << 16));
|
||||
l2 = len;
|
||||
}
|
||||
int i = line.Find(ToLower(wl[0], charset) +
|
||||
(ToLower(wl[1], charset) << 8) +
|
||||
(ToLower(wl[2], charset) << 16));
|
||||
if(i >= 0) {
|
||||
const byte *s = line[i].begin;
|
||||
const byte *e = line[i].end;
|
||||
int capitals = 0;
|
||||
char q[64];
|
||||
int pos = 0;
|
||||
String q;
|
||||
while(s < e)
|
||||
if(*s < dict) {
|
||||
if(pos == len && compare3(q, w, wl, len))
|
||||
if(q.GetLength() == len && memcmp(w, q, q.GetLength()) == 0)
|
||||
return true;
|
||||
pos = *s++;
|
||||
ASSERT(pos < 64);
|
||||
capitals = 0;
|
||||
if(q.GetLength() == l2 && memcmp(wl, q, q.GetLength()) == 0)
|
||||
return true;
|
||||
q.Trim(*s++);
|
||||
}
|
||||
else {
|
||||
ASSERT(*s >= dict);
|
||||
const char *x = voc[(int)*s++ - dict];
|
||||
while(*x)
|
||||
q[pos++] = *x++;
|
||||
ASSERT(pos < 64);
|
||||
q.Cat(x);
|
||||
}
|
||||
if(pos == len && compare3(q, w, wl, len))
|
||||
if(q.GetLength() == len && memcmp(w, q, q.GetLength()) == 0)
|
||||
return true;
|
||||
if(q.GetLength() == l2 && memcmp(wl, q, q.GetLength()) == 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue