Win32: Added spellchecker code. Must be defined __GOLD_SPELL__ to enable.
This commit is contained in:
parent
df30d36fe5
commit
b1ea7b88dd
@ -764,6 +764,11 @@ CfgGed::CfgGed() {
|
||||
replylinkfloat = true;
|
||||
replylinklist = 0;
|
||||
replylinkshowalways = true;
|
||||
#if defined(__GOLD_SPELL__)
|
||||
scheckerdeflang = 0xFFFF;
|
||||
scheckerenabled = NO;
|
||||
strcpy(scheckeruserdic, "user.dic");
|
||||
#endif
|
||||
screenblanker = 180;
|
||||
screenblankertype = BLANK_SLIDEWIN;
|
||||
screenmaxcol = 0;
|
||||
|
@ -320,6 +320,11 @@ const word CRC_REPLYLINKFLOAT = 0xA3EC;
|
||||
const word CRC_REPLYLINKLIST = 0x104F;
|
||||
const word CRC_REPLYLINKSHOWALWAYS = 0x2BCD;
|
||||
const word CRC_ROBOTNAME = 0x7393;
|
||||
#if defined(__GOLD_SPELL__)
|
||||
const word CRC_SCHECKERDEFLANG = 0xBBEB;
|
||||
const word CRC_SCHECKERENABLED = 0x7394;
|
||||
const word CRC_SCHECKERUSERDIC = 0x0753;
|
||||
#endif
|
||||
const word CRC_SCREENBLANKER = 0x5CF7;
|
||||
const word CRC_SCREENMAXCOL = 0xFFFC;
|
||||
const word CRC_SCREENMAXROW = 0xFDF7;
|
||||
|
@ -519,6 +519,11 @@ SwitchR:
|
||||
|
||||
SwitchS:
|
||||
switch(crc) {
|
||||
#if defined(__GOLD_SPELL__)
|
||||
case CRC_SCHECKERDEFLANG : CfgScheckerdeflang (); break;
|
||||
case CRC_SCHECKERENABLED : CfgScheckerenabled (); break;
|
||||
case CRC_SCHECKERUSERDIC : CfgScheckeruserdic (); break;
|
||||
#endif
|
||||
case CRC_SCREENBLANKER : CfgScreenblanker (); break;
|
||||
case CRC_SCREENMAXCOL : CfgScreenmaxcol (); break;
|
||||
case CRC_SCREENMAXROW : CfgScreenmaxrow (); break;
|
||||
|
@ -222,6 +222,31 @@ void CfgRobotname() {
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
void CfgScheckerdeflang()
|
||||
{
|
||||
CFG->scheckerdeflang = atoi(val);
|
||||
if (CFG->scheckerdeflang == 0)
|
||||
CFG->scheckerdeflang = 0xFFFF;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CfgScheckerenabled()
|
||||
{
|
||||
CFG->scheckerenabled = GetYesno(val);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CfgScheckeruserdic()
|
||||
{
|
||||
strcpy(CFG->scheckeruserdic, val);
|
||||
}
|
||||
#endif
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CfgScreenblanker() {
|
||||
|
||||
GTok t;
|
||||
|
@ -671,6 +671,9 @@ tglobalkey globalkeys[] = {
|
||||
{ CRC_READSHOWDEL , KK_ReadShowDel , KT_R }, // 0x8615
|
||||
{ CRC_K_ENTER , Key_Ent , 0 }, // 0x87BD
|
||||
{ CRC_EDITGOTOPLINE , KK_EditGoTopLine , KT_E }, // 0x87C2
|
||||
#if defined(__GOLD_SPELL__)
|
||||
{ CRC_EDITSCHECKERMENU , KK_EditSCheckerMenu , KT_E }, // 0x881F
|
||||
#endif
|
||||
{ CRC_HEADERTOGGLEARCSENT , KK_HeaderToggleArcsent , KT_H }, // 0x88A7
|
||||
{ CRC_EDITBLOCKPGDN , KK_EditBlockPgDn , KT_E }, // 0x895B
|
||||
{ CRC_EDITASKEXIT , KK_EditAskExit , KT_E }, // 0x89AF
|
||||
|
@ -112,6 +112,9 @@ const word CRC_EDITQUITNOW = 0x80BA;
|
||||
const word CRC_EDITREFLOW = 0x13F9;
|
||||
const word CRC_EDITSAVEFILE = 0x64A4;
|
||||
const word CRC_EDITSAVEMSG = 0x660C;
|
||||
#if defined(__GOLD_SPELL__)
|
||||
const word CRC_EDITSCHECKERMENU = 0x881F;
|
||||
#endif
|
||||
const word CRC_EDITSCODENORMAL = 0xE4CE;
|
||||
const word CRC_EDITSCODEBOLD = 0x657D;
|
||||
const word CRC_EDITSCODEITALIC = 0x487F;
|
||||
|
@ -222,6 +222,14 @@ const word CRC_STYLECODE = 0x8B6C;
|
||||
const word CRC_STYLECODES = 0x4CB0;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
const word CRC_SPELL = 0xB8AE;
|
||||
const word CRC_SCERROR = 0xAB65;
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Get color value
|
||||
|
||||
@ -414,6 +422,11 @@ void GetColors(char* value) {
|
||||
case CRC_STYLECODES:
|
||||
wptr = &GC_STYLE_;
|
||||
break;
|
||||
#if defined(__GOLD_SPELL__)
|
||||
case CRC_SPELL:
|
||||
wptr = &GC_SPELL_;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -577,6 +590,11 @@ void GetColors(char* value) {
|
||||
wptr->_ReverseBoldItalicUnderscore = attr;
|
||||
}
|
||||
break;
|
||||
#if defined(__GOLD_SPELL__)
|
||||
case CRC_SCERROR:
|
||||
wptr->_SpellError = attr;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -306,6 +306,11 @@ void CfgReplylinklist ();
|
||||
void CfgReplylinkshowalways();
|
||||
void CfgReplyto ();
|
||||
void CfgRobotname ();
|
||||
#if defined(__GOLD_SPELL__)
|
||||
void CfgScheckerdeflang ();
|
||||
void CfgScheckerenabled ();
|
||||
void CfgScheckeruserdic ();
|
||||
#endif
|
||||
void CfgScreenblanker ();
|
||||
void CfgScreenmaxcol ();
|
||||
void CfgScreenmaxrow ();
|
||||
|
@ -638,6 +638,9 @@ struct SaveUtil {
|
||||
#define GC_CFGB_ CFG->color[11]
|
||||
#define GC_STYLE_ CFG->color[12]
|
||||
#define GC_SHAD_ CFG->color[13]
|
||||
#if defined(__GOLD_SPELL__)
|
||||
#define GC_SPELL_ CFG->color[14]
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -690,6 +693,10 @@ struct SaveUtil {
|
||||
#define _ReverseItalicUnderscore c[14]
|
||||
#define _ReverseBoldItalicUnderscore c[15]
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
#define _SpellError c[0]
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Window part colors
|
||||
@ -806,6 +813,10 @@ struct SaveUtil {
|
||||
#define C_STYLERUI_ GC_STYLE_._ReverseItalicUnderscore
|
||||
#define C_STYLERUIB GC_STYLE_._ReverseBoldItalicUnderscore
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
#define C_SCERROR GC_SPELL_._SpellError
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Window handles
|
||||
|
@ -309,6 +309,11 @@ public:
|
||||
int replylinklist;
|
||||
bool replylinkshowalways;
|
||||
gstrarray robotname;
|
||||
#if defined(__GOLD_SPELL__)
|
||||
word scheckerdeflang;
|
||||
int scheckerenabled;
|
||||
Path scheckeruserdic;
|
||||
#endif
|
||||
int screenblanker; // blanktime;
|
||||
int screenblankertype;
|
||||
int screenmaxcol; // maxcols;
|
||||
|
@ -93,6 +93,16 @@ void IEclass::debugtest(char* __test, int __a, int __b, char* __file, int __line
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
inline bool isscchar(int c)
|
||||
{
|
||||
return isxalnum(c) || (c == '-') || (c == '\'') || (c == '.') ;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Make sure line type is correct
|
||||
|
||||
@ -240,6 +250,207 @@ void IEclass::gotorowcol(uint __col, uint __row) {
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
void IEclass::dispstringsc(char *__buf, uint __beg, uint __end, uint __row, uint __col, char endchar)
|
||||
{
|
||||
char scbuf[EDIT_BUFLEN];
|
||||
|
||||
uint bbeg = __beg;
|
||||
uint bend = __beg;
|
||||
uint bpos = __beg;
|
||||
|
||||
if ((bbeg > 0) && isscchar(__buf[bbeg]) && isscchar(__buf[bbeg-1]))
|
||||
{
|
||||
for (; (bpos < __end) && isscchar(__buf[bpos]); bpos++);
|
||||
bend = bpos;
|
||||
}
|
||||
|
||||
while (bpos < __end)
|
||||
{
|
||||
for (; (bpos < __end) && !isscchar(__buf[bpos]); bpos++);
|
||||
bend = bpos;
|
||||
|
||||
uint scpos = 0;
|
||||
for (; (bpos < __end) && isscchar(__buf[bpos]); bpos++, scpos++)
|
||||
scbuf[scpos] = __buf[bpos];
|
||||
|
||||
if ((scpos == 0) || ((bpos == __end) && isscchar(endchar)))
|
||||
{
|
||||
bend = bpos;
|
||||
break;
|
||||
}
|
||||
|
||||
scbuf[scpos] = NUL;
|
||||
|
||||
if (schecker.Check(scbuf))
|
||||
bend = bpos;
|
||||
else
|
||||
{
|
||||
char savechar = __buf[bend];
|
||||
__buf[bend] = NUL;
|
||||
StyleCodeHighlight(__buf+bbeg, __row, __col+bbeg-__beg, false, -1);
|
||||
__buf[bend] = savechar;
|
||||
|
||||
bbeg = bend; bend += scpos;
|
||||
|
||||
bool oldusestylies = AA->adat->usestylies;
|
||||
bool oldhighlighturls = CFG->highlighturls;
|
||||
AA->adat->usestylies = false;
|
||||
CFG->highlighturls = false;
|
||||
|
||||
savechar = __buf[bend];
|
||||
__buf[bend] = NUL;
|
||||
StyleCodeHighlight(__buf+bbeg, __row, __col+bbeg-__beg, false, C_SCERROR);
|
||||
__buf[bend] = savechar;
|
||||
|
||||
AA->adat->usestylies = oldusestylies;
|
||||
CFG->highlighturls = oldhighlighturls;
|
||||
|
||||
bbeg = bend;
|
||||
}
|
||||
}
|
||||
|
||||
if (bbeg < bend)
|
||||
StyleCodeHighlight(__buf+bbeg, __row, __col+bbeg-__beg, false, -1);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void IEclass::dispstring(Line* line, uint __row)
|
||||
{
|
||||
GFTRK("Editdispstring");
|
||||
|
||||
// Get string length
|
||||
uint _length = strlen(line->txt.c_str());
|
||||
|
||||
// String longer than window width?
|
||||
_test_haltab(_length > (maxcol+1), _length, (maxcol+1));
|
||||
_length = MinV(_length, (maxcol+1));
|
||||
|
||||
// Buffer for translation to visual representation
|
||||
char _buf[EDIT_BUFLEN];
|
||||
|
||||
// Space-pad and nul-terminate the buffer
|
||||
memset(_buf, ' ', maxcol+1);
|
||||
_buf[maxcol+1] = NUL;
|
||||
|
||||
// Copy/translate string into buffer
|
||||
for (uint _pos = 0; _pos < _length; _pos++)
|
||||
{
|
||||
char chr = line->txt[_pos];
|
||||
switch (chr)
|
||||
{
|
||||
case ' ': _buf[_pos] = EDIT->CharSpace(); break;
|
||||
case '\n': _buf[_pos] = EDIT->CharPara(); break;
|
||||
default: _buf[_pos] = chr;
|
||||
}
|
||||
}
|
||||
|
||||
int selected = 0;
|
||||
uint begblock = 0;
|
||||
uint endblock = 0;
|
||||
Line *fbline = NULL;
|
||||
Line *lbline = NULL;
|
||||
|
||||
if (blockcol != -1)
|
||||
{
|
||||
for (Line *ln = findfirstline(); ln; ln = ln->next)
|
||||
{
|
||||
if (ln == currline)
|
||||
{
|
||||
if (selected) { lbline = ln; selected ^= 1; endblock = col; }
|
||||
else { fbline = ln; selected ^= 1; begblock = col; }
|
||||
}
|
||||
|
||||
if (ln->type & GLINE_BLOK)
|
||||
{
|
||||
if (selected) { lbline = ln; selected ^= 1; endblock = blockcol; }
|
||||
else { fbline = ln; selected ^= 1; begblock = blockcol; }
|
||||
}
|
||||
|
||||
if (ln == line) { if (ln == lbline) selected = 1; break; }
|
||||
if (lbline) break;
|
||||
}
|
||||
|
||||
if (selected)
|
||||
{
|
||||
if (fbline == lbline)
|
||||
{
|
||||
if (begblock > endblock)
|
||||
{
|
||||
int temp = begblock;
|
||||
begblock = endblock;
|
||||
endblock = temp;
|
||||
}
|
||||
else if (begblock == endblock)
|
||||
begblock = endblock = 0;
|
||||
}
|
||||
else if (line == fbline)
|
||||
endblock = maxcol+1;
|
||||
else if (line == lbline)
|
||||
begblock = 0;
|
||||
else
|
||||
{
|
||||
begblock = 0;
|
||||
endblock = maxcol+1;
|
||||
}
|
||||
}
|
||||
else
|
||||
begblock = endblock = 0;
|
||||
}
|
||||
|
||||
|
||||
if (0 < begblock)
|
||||
{
|
||||
char savechar = _buf[begblock];
|
||||
_buf[begblock] = NUL;
|
||||
|
||||
if ((CFG->scheckerenabled == GAUTO) && schecker.IsLoaded() &&
|
||||
!(line->type & (GLINE_TAGL|GLINE_QUOT|GLINE_KLUD|GLINE_TEAR|GLINE_ORIG|GLINE_HIDD)))
|
||||
{
|
||||
dispstringsc(_buf, 0, begblock, __row, mincol, savechar);
|
||||
}
|
||||
else
|
||||
StyleCodeHighlight(_buf, __row, mincol, false, -1);
|
||||
|
||||
_buf[begblock] = savechar;
|
||||
}
|
||||
|
||||
if (begblock < endblock)
|
||||
{
|
||||
bool oldusestylies = AA->adat->usestylies;
|
||||
bool oldhighlighturls = CFG->highlighturls;
|
||||
AA->adat->usestylies = false;
|
||||
CFG->highlighturls = false;
|
||||
|
||||
char savechar = _buf[endblock];
|
||||
_buf[endblock] = NUL;
|
||||
StyleCodeHighlight(_buf+begblock, __row, mincol+begblock, false, C_READA);
|
||||
_buf[endblock] = savechar;
|
||||
|
||||
AA->adat->usestylies = oldusestylies;
|
||||
CFG->highlighturls = oldhighlighturls;
|
||||
}
|
||||
|
||||
if (endblock < (maxcol+1))
|
||||
{
|
||||
if ((CFG->scheckerenabled == GAUTO) && schecker.IsLoaded() &&
|
||||
!(line->type & (GLINE_TAGL|GLINE_QUOT|GLINE_KLUD|GLINE_TEAR|GLINE_ORIG|GLINE_HIDD)))
|
||||
{
|
||||
dispstringsc(_buf, endblock, maxcol+1, __row, mincol+endblock, 0);
|
||||
}
|
||||
else
|
||||
StyleCodeHighlight(_buf+endblock, __row, mincol+endblock, false, -1);
|
||||
}
|
||||
|
||||
GFTRK(NULL);
|
||||
}
|
||||
#else //#if defined(__GOLD_SPELL__)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void IEclass::dispstring(const char* __string, uint __row, int attr, Line* line) {
|
||||
@ -353,6 +564,7 @@ void IEclass::dispstring(const char* __string, uint __row, int attr, Line* line)
|
||||
|
||||
GFTRK(NULL);
|
||||
}
|
||||
#endif //#if defined(__GOLD_SPELL__)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -392,7 +604,11 @@ void IEclass::displine(Line* __line, uint __row) {
|
||||
|
||||
// Display line
|
||||
setcolor(__line);
|
||||
#if defined(__GOLD_SPELL__)
|
||||
dispstring(__line, __row);
|
||||
#else
|
||||
dispstring(__line->txt.c_str(), __row, -1, __line);
|
||||
#endif
|
||||
|
||||
GFTRK(NULL);
|
||||
}
|
||||
@ -436,6 +652,12 @@ void IEclass::refresh(Line* __currline, uint __row) {
|
||||
}
|
||||
|
||||
// If we ran out of lines, blank the rest
|
||||
#if defined(__GOLD_SPELL__)
|
||||
if (__row <= maxrow)
|
||||
editwin.fill(__row, mincol, __row, maxcol, _box_table(W_BREAD, 1), C_READB|ACSET);
|
||||
if (++__row <= maxrow)
|
||||
editwin.fill(__row, mincol, maxrow, maxcol, ' ', C_READW);
|
||||
#else
|
||||
if(__row <= maxrow) {
|
||||
vchar vbuf[256];
|
||||
for(int c = 0; c < maxcol+1; c++)
|
||||
@ -445,6 +667,7 @@ void IEclass::refresh(Line* __currline, uint __row) {
|
||||
while(__row <= maxrow)
|
||||
dispstring("", __row++);
|
||||
}
|
||||
#endif
|
||||
|
||||
GFTRK(NULL);
|
||||
}
|
||||
@ -1859,6 +2082,58 @@ void IEclass::SaveMsg() {
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
void IEclass::SCheckerMenu()
|
||||
{
|
||||
if (!schecker.IsLoaded())
|
||||
return;
|
||||
|
||||
const char *txt = currline->txt.c_str();
|
||||
GMenuSChecker menu;
|
||||
int finaltag;
|
||||
|
||||
if (!isscchar(txt[col]))
|
||||
finaltag = menu.Run(schecker, "");
|
||||
else
|
||||
{
|
||||
char buff[EDIT_BUFLEN];
|
||||
size_t beg = col;
|
||||
size_t end = col;
|
||||
|
||||
for (; (beg > 0) && isscchar(txt[beg-1]); beg--);
|
||||
for (; isscchar(txt[end]); end++);
|
||||
size_t len = end - beg;
|
||||
|
||||
memcpy(buff, &txt[beg], len);
|
||||
buff[len] = 0;
|
||||
|
||||
finaltag = menu.Run(schecker, buff);
|
||||
if (finaltag >= 0)
|
||||
{
|
||||
std::string &str = schecker.GetSuggest()[finaltag].second;
|
||||
size_t len2 = str.length() - 3;
|
||||
txt = &str.c_str()[2];
|
||||
|
||||
if ((buff[len-1] == '.') && (txt[len2-1] != '.')) len--;
|
||||
if (col > (beg + len2 - 1)) col = beg + len2 - 1;
|
||||
|
||||
Undo->PushItem(EDIT_UNDO_DEL_TEXT, currline, beg, len);
|
||||
currline->txt.erase(beg, len);
|
||||
|
||||
Undo->PushItem(EDIT_UNDO_INS_TEXT|BATCH_MODE, currline, beg, len2);
|
||||
currline->txt.insert(beg, txt, len2);
|
||||
wrapit(&currline, &col, &row);
|
||||
}
|
||||
}
|
||||
|
||||
if (finaltag == -2)
|
||||
refresh(currline, row);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
int IEclass::isempty(Line* __line) {
|
||||
@ -2476,6 +2751,9 @@ noselecting:
|
||||
case KK_EditReflow: Reflow(); break;
|
||||
case KK_EditSaveFile: SaveFile(); break;
|
||||
case KK_EditSaveMsg: SaveMsg(); break;
|
||||
#if defined(__GOLD_SPELL__)
|
||||
case KK_EditSCheckerMenu: SCheckerMenu(); break;
|
||||
#endif
|
||||
case KK_EditSoundkill: Soundkill(); break;
|
||||
case KK_EditSpellCheck: SpellCheck(); break;
|
||||
case KK_EditTab: Tab(); break;
|
||||
@ -2527,6 +2805,14 @@ int IEclass::Start(int __mode, uint* __position, GMsg* __msg) {
|
||||
msgmode = __mode;
|
||||
currline = __msg->lin;
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
if (CFG->scheckerenabled)
|
||||
{
|
||||
schecker.Init();
|
||||
schecker.Load(CFG->scheckerdeflang, CFG->scheckeruserdic);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(AA->isinternet() and (CFG->soupexportmargin <= CFG->dispmargin))
|
||||
margintext = CFG->soupexportmargin;
|
||||
else
|
||||
|
@ -279,6 +279,12 @@ protected:
|
||||
int blockcol;
|
||||
int selecting;
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Speller.
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
CSpellChecker schecker;
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Internal helper functions
|
||||
@ -290,7 +296,12 @@ protected:
|
||||
int dispchar (vchar __ch, int attr=-1);
|
||||
void dispins ();
|
||||
void displine (Line* __line, uint __row);
|
||||
#if defined(__GOLD_SPELL__)
|
||||
void dispstringsc (char *__buf, uint __beg, uint __end, uint __row, uint __col, char endchar);
|
||||
void dispstring (Line* line, uint __row);
|
||||
#else
|
||||
void dispstring (const char* __string, uint __row, int attr=-1, Line* line=NULL);
|
||||
#endif
|
||||
int downoneline (uint __row);
|
||||
void editexport (Line* __exportline, int __endat);
|
||||
Line* findanchor ();
|
||||
@ -395,6 +406,9 @@ public:
|
||||
void ReTab ();
|
||||
void SaveFile ();
|
||||
void SaveMsg ();
|
||||
#if defined(__GOLD_SPELL__)
|
||||
void SCheckerMenu ();
|
||||
#endif
|
||||
void Soundkill ();
|
||||
void SpellCheck ();
|
||||
void Tab ();
|
||||
|
@ -181,6 +181,9 @@ const gkey KK_EditSCodeBold = 0xFF09;
|
||||
const gkey KK_EditSCodeItalic = 0xFF0A;
|
||||
const gkey KK_EditSCodeUnderline = 0xFF0B;
|
||||
const gkey KK_EditSCodeReverse = 0xFF0C;
|
||||
#if defined(__GOLD_SPELL__)
|
||||
const gkey KK_EditSCheckerMenu = 0xFF0D;
|
||||
#endif
|
||||
|
||||
const gkey KK_FileAbort = 0xFF10;
|
||||
const gkey KK_FileAskExit = 0xFF11;
|
||||
|
@ -1070,3 +1070,137 @@ int GMenuConfirm::Run() {
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
int GMenuSChecker::Run(CSpellChecker &schecker, const char *word)
|
||||
{
|
||||
enum
|
||||
{
|
||||
TAG_ADDWORD = 100,
|
||||
TAG_LANG = 0x10000,
|
||||
TAG_MORE = 0x20000,
|
||||
TAG_INDEX = 0x30000
|
||||
};
|
||||
|
||||
schecker.Check(word);
|
||||
CSpellSuggestV &suggest = schecker.Suggest();
|
||||
|
||||
std::string title;
|
||||
if (!*word)
|
||||
title = " SChecker ";
|
||||
else
|
||||
{
|
||||
title = " ";
|
||||
title += word;
|
||||
title += " ";
|
||||
}
|
||||
|
||||
Init();
|
||||
SetColor(C_ASKW, C_ASKQ, C_ASKN, C_ASKS, CFG->switches.get(screenshadows) ? C_SHADOW : -1);
|
||||
SetTitle(title.c_str(), C_ASKT, TLEFT);
|
||||
SetPos(6, 0, title.length()+2, 0);
|
||||
SetBorder(W_BASK, C_ASKB);
|
||||
SetMask(M_CLALL);
|
||||
SetHelp(0);
|
||||
|
||||
Begin();
|
||||
SetTitle("");
|
||||
|
||||
size_t idx;
|
||||
size_t levels = 0;
|
||||
size_t numrows = 7;
|
||||
|
||||
CSpellLangV &langs = schecker.GetLangs();
|
||||
LIDC lidc = schecker.GetLangCode();
|
||||
|
||||
std::vector<std::string> langstr;
|
||||
size_t langcount = langs.size();
|
||||
|
||||
for (idx = 0; idx < langcount; idx++)
|
||||
{
|
||||
char buff[10];
|
||||
LIDC code = langs[idx].GetLangCode();
|
||||
|
||||
buff[0] = ' ';
|
||||
buff[1] = (code == lidc) ? '\x10' : ' ';
|
||||
|
||||
itoa(code, &buff[2], 10);
|
||||
strcat(buff, " ");
|
||||
|
||||
langstr.push_back(std::string(buff));
|
||||
}
|
||||
|
||||
if (langcount)
|
||||
{
|
||||
Item(TAG_LANG, "L Language... ", 0);
|
||||
numrows++;
|
||||
|
||||
SetPos(numrows, 1, 0, 0);
|
||||
Begin();
|
||||
|
||||
for (idx = 0; idx < langcount; idx++)
|
||||
Item(TAG_LANG+idx+1, langstr[idx].c_str());
|
||||
|
||||
End();
|
||||
}
|
||||
|
||||
if (*word)
|
||||
{
|
||||
Item(TAG_ADDWORD, "A Add Word... ");
|
||||
numrows++;
|
||||
}
|
||||
|
||||
if (suggest.size())
|
||||
{
|
||||
ItemSep();
|
||||
numrows++;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < suggest.size(); idx++)
|
||||
{
|
||||
Item(TAG_INDEX + idx, suggest[idx].second.c_str());
|
||||
|
||||
if ((numrows == (gvid->numrows - 5)) && (idx < suggest.size()-3))
|
||||
{
|
||||
ItemSep();
|
||||
Item(TAG_MORE + levels, "M More... ", 0);
|
||||
|
||||
levels++;
|
||||
numrows = levels + 6;
|
||||
|
||||
SetPos(numrows, levels, title.length()+2, 0);
|
||||
BeginPullDown();
|
||||
}
|
||||
|
||||
numrows++;
|
||||
}
|
||||
|
||||
for (size_t n = 0; n < levels; n++)
|
||||
End();
|
||||
|
||||
if (suggest.size())
|
||||
SetTag(TAG_INDEX);
|
||||
|
||||
End();
|
||||
|
||||
vcurhide();
|
||||
Start();
|
||||
vcurshow();
|
||||
|
||||
if (finaltag == TAG_ADDWORD)
|
||||
{
|
||||
schecker.AddWord();
|
||||
return -2;
|
||||
}
|
||||
else if ((finaltag > TAG_LANG) && (finaltag < TAG_MORE))
|
||||
{
|
||||
schecker.Load(langs[finaltag-TAG_LANG-1].GetLangCode(), CFG->scheckeruserdic);
|
||||
return -2;
|
||||
}
|
||||
|
||||
return (finaltag < TAG_INDEX) ? -1 : (finaltag - TAG_INDEX);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
|
@ -304,3 +304,14 @@ public:
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
class GMenuSChecker : public GMnu
|
||||
{
|
||||
public:
|
||||
int Run(CSpellChecker &schecker, const char *word);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
|
@ -78,6 +78,7 @@
|
||||
#include <gwinhelp.h>
|
||||
#include <gwinpick.h>
|
||||
#include <gedacfg.h>
|
||||
#include <gespell.h>
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
498
goldlib/gall/gespell.cpp
Normal file
498
goldlib/gall/gespell.cpp
Normal file
@ -0,0 +1,498 @@
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// GoldED+
|
||||
// Copyright (C) 1990-1999 Odinn Sorensen
|
||||
// Copyright (C) 1999-2000 Alexander S. Aganichev
|
||||
// ------------------------------------------------------------------
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
// MA 02111-1307 USA
|
||||
// ------------------------------------------------------------------
|
||||
// $Id$
|
||||
// ------------------------------------------------------------------
|
||||
// SpellChecker functions.
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
/* C4786: 'identifier' : identifier was truncated to 'number'
|
||||
characters in the debug information
|
||||
*/
|
||||
#pragma warning(disable: 4786)
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gstrall.h>
|
||||
#include <gespell.h>
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__WIN32__)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#define CHECK_ERROR(jump) if (error != ERROR_SUCCESS) goto jump
|
||||
#define CHECK_NULL(ptr, jump) if (ptr == NULL) goto jump
|
||||
#define CHECK_SEC(jump) if ((sec & 0xFF) != SC_SEC_NoErrors) goto jump
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
const char SC_RKEY_Prooftools[] = "Software\\Microsoft\\Shared Tools\\Proofing Tools";
|
||||
const char SC_RKEY_Grammar[] = "Grammar";
|
||||
const char SC_RKEY_Spelling[] = "Spelling";
|
||||
const char SC_RKEY_Hyphenation[] = "Hyphenation";
|
||||
const char SC_RKEY_Thesaurus[] = "Thesaurus";
|
||||
|
||||
// Spell Check Command Code
|
||||
const SCCC SC_SCCC_VerifyWord = 1;
|
||||
const SCCC SC_SCCC_VerifyBuffer = 2;
|
||||
const SCCC SC_SCCC_Suggest = 3;
|
||||
const SCCC SC_SCCC_SuggestMore = 4;
|
||||
const SCCC SC_SCCC_HyphInfo = 5;
|
||||
const SCCC SC_SCCC_Wildcard = 6;
|
||||
const SCCC SC_SCCC_Anagram = 7;
|
||||
|
||||
// Spell Check Return Status
|
||||
const SCRS SC_SRCS_NoErrors = 0;
|
||||
const SCRS SC_SRCS_UnknownInputWord = 1;
|
||||
const SCRS SC_SRCS_ReturningChangeAlways = 2;
|
||||
const SCRS SC_SRCS_ReturningChangeOnce = 3;
|
||||
const SCRS SC_SRCS_InvalidHyphenation = 4;
|
||||
const SCRS SC_SRCS_ErrorCapitalization = 5;
|
||||
const SCRS SC_SRCS_WordConsideredAbbreviation = 6;
|
||||
const SCRS SC_SRCS_HyphChangesSpelling = 7;
|
||||
const SCRS SC_SRCS_NoMoreSuggestions = 8;
|
||||
const SCRS SC_SRCS_MoreInfoThanBufferCouldHold = 9;
|
||||
const SCRS SC_SRCS_NoSentenceStartCap = 10;
|
||||
const SCRS SC_SRCS_RepeatWord = 11;
|
||||
const SCRS SC_SRCS_ExtraSpaces = 12;
|
||||
const SCRS SC_SRCS_MissingSpace = 13;
|
||||
const SCRS SC_SRCS_InitialNumeral = 14;
|
||||
|
||||
// Major Error Codes (Low Byte of SEC)
|
||||
const SEC SC_SEC_NoErrors = 0;
|
||||
const SEC SC_SEC_OOM = 1;
|
||||
const SEC SC_SEC_ModuleError = 2;
|
||||
const SEC SC_SEC_IOErrorMdr = 3;
|
||||
const SEC SC_SEC_IOErrorUdr = 4;
|
||||
|
||||
// Minor Error Codes (High Byte of SEC)
|
||||
const SEC SC_SEC_ModuleAlreadyBusy = 128 << 8;
|
||||
const SEC SC_SEC_InvalidID = 129 << 8;
|
||||
const SEC SC_SEC_InvalidWsc = 130 << 8;
|
||||
const SEC SC_SEC_InvalidMdr = 131 << 8;
|
||||
const SEC SC_SEC_InvalidUdr = 132 << 8;
|
||||
const SEC SC_SEC_InvalidSCC = 133 << 8;
|
||||
const SEC SC_SEC_InvalidMainDict = 134 << 8;
|
||||
const SEC SC_SEC_OperNotMatchedUserDict = 135 << 8;
|
||||
const SEC SC_SEC_FileReadError = 136 << 8;
|
||||
const SEC SC_SEC_FileWriteError = 137 << 8;
|
||||
const SEC SC_SEC_FileCreateError = 138 << 8;
|
||||
const SEC SC_SEC_FileShareError = 139 << 8;
|
||||
const SEC SC_SEC_ModuleNotTerminated = 140 << 8;
|
||||
const SEC SC_SEC_UserDictFull = 141 << 8;
|
||||
const SEC SC_SEC_InvalidUdrEntry = 142 << 8;
|
||||
const SEC SC_SEC_UdrEntryTooLong = 143 << 8;
|
||||
const SEC SC_SEC_MdrCountExceeded = 144 << 8;
|
||||
const SEC SC_SEC_UdrCountExceeded = 145 << 8;
|
||||
const SEC SC_SEC_FileOpenError = 146 << 8;
|
||||
const SEC SC_SEC_FileTooLargeError = 147 << 8;
|
||||
const SEC SC_SEC_UdrReadOnly = 148 << 8;
|
||||
|
||||
// Spell Options bitfield definitions
|
||||
const dword SC_SO_SuggestFromUserDict = 0x0001; // Scan UDR as well as MDR
|
||||
const dword SC_SO_IgnoreAllCaps = 0x0002; // Ignore a word if all upppercase
|
||||
const dword SC_SO_IgnoreMixedDigits = 0x0004; // Ignore word if has any numbers in it
|
||||
const dword SC_SO_IgnoreRomanNumerals = 0x0008; // Ignore word composed of all roman numerals
|
||||
const dword SC_SO_FindUncappedSentences = 0x0010; // Flag sentences which don't start with a cap
|
||||
const dword SC_SO_FindMissingSpaces = 0x0020; // Find missing spaces between words/sentences
|
||||
const dword SC_SO_FindRepeatWord = 0x0040; // CSAPI to flag repeated words
|
||||
const dword SC_SO_FindExtraSpaces = 0x0080; // CSAPI to flag extra spaces between words
|
||||
const dword SC_SO_FindSpacesBeforePunc = 0x0100; // CSAPI to flag space preceeding certain punc
|
||||
const dword SC_SO_FindSpacesAfterPunc = 0x0200; // CSAPI to flag space after certain punc
|
||||
const dword SC_SO_RateSuggestions = 0x0400;
|
||||
// All suggestions returned should be given some scaled value
|
||||
// corresponding to liklihood of being correct alternative.
|
||||
// Scale is 1..255, 255 most likely correction and 1 least likely
|
||||
const dword SC_SO_FindInitialNumerals = 0x0800; // Flag words starting with number(s)
|
||||
const dword SC_SO_ReportUDHits = 0x1000;
|
||||
// Report (via scrsNoErrorsUDHit) where user dict was used during verification
|
||||
const dword SC_SO_QuickSuggest = 0x2000; // Don't use typo suggest code (Soft-Art only)
|
||||
const dword SC_SO_UseAllOpenUdr = 0x4000;
|
||||
// Automatically use all udr's opened after this option is set,
|
||||
// or all opened udr's with mdr's opened after this option is set.
|
||||
// This option does not allow exclusion dicts to be edited. (HM only)
|
||||
const dword SC_SO_SwapMdr = 0x8000;
|
||||
// Keep the most recent 2 mdr's around. swap between them instead of actually
|
||||
// closing and reopening mdr's. (HM only)
|
||||
const dword SC_SO_SglStepSugg = 0x10000;
|
||||
// Break after each suggestion task for faster return of control to the
|
||||
// application. (HM only)
|
||||
|
||||
const dword SC_SO_LangMode = 0xF0000000; // Language Mode mask
|
||||
// Hebrew Language Modes -- (CT only)
|
||||
const dword SC_SO_HebrewFullScript = 0x00000000;
|
||||
const dword SC_SO_HebrewPartialScript = 0x10000000;
|
||||
const dword SC_SO_HebrewMixedScript = 0x20000000;
|
||||
const dword SC_SO_HebrewMixedAuthorizedScript = 0x30000000;
|
||||
// French Language Modes -- (HM only)
|
||||
const dword SC_SO_FrenchDialectDefault = 0x00000000;
|
||||
const dword SC_SO_FrenchUnaccentedUppercase = 0x10000000;
|
||||
const dword SC_SO_FrenchAccentedUppercase = 0x20000000;
|
||||
// Russian Language Modes -- (HM only)
|
||||
const dword SC_SO_RussianDialectDefault = 0x00000000;
|
||||
const dword SC_SO_RussianIE = 0x10000000;
|
||||
const dword SC_SO_RussianIO = 0x20000000;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
bool CSpellLang::Init(HKEY hKey, const char *name)
|
||||
{
|
||||
bool result = false;
|
||||
int error;
|
||||
HKEY hKeyLang;
|
||||
|
||||
byte engine[_MAX_PATH];
|
||||
byte dictionary[_MAX_PATH];
|
||||
unsigned long esize = sizeof(engine);
|
||||
unsigned long dsize = sizeof(dictionary);
|
||||
|
||||
mLIDC = atoi(name);
|
||||
|
||||
error = RegOpenKeyEx(hKey, name, 0, KEY_READ, &hKeyLang);
|
||||
CHECK_ERROR(cleanup0);
|
||||
|
||||
error = RegQueryValueEx(hKeyLang, "Engine", NULL, NULL, engine, &esize);
|
||||
CHECK_ERROR(cleanup1);
|
||||
error = RegQueryValueEx(hKeyLang, "Dictionary", NULL, NULL, dictionary, &dsize);
|
||||
CHECK_ERROR(cleanup1);
|
||||
|
||||
strcpy(mEngine, (char*)engine);
|
||||
strcpy(mDictionary, (char*)dictionary);
|
||||
|
||||
result = true;
|
||||
|
||||
cleanup1:
|
||||
RegCloseKey(hKeyLang);
|
||||
cleanup0:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
bool CSpellLang::Load(const char *userdic)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
mLibrary = LoadLibrary(mEngine);
|
||||
CHECK_NULL(mLibrary, cleanup0);
|
||||
|
||||
mSpellVer = (SpellVer_fn ) GetProcAddress(mLibrary, "SpellVer" ); CHECK_NULL(mSpellVer, cleanup1);
|
||||
mSpellInit = (SpellInit_fn ) GetProcAddress(mLibrary, "SpellInit" ); CHECK_NULL(mSpellInit, cleanup1);
|
||||
mSpellOptions = (SpellOptions_fn ) GetProcAddress(mLibrary, "SpellOptions" ); CHECK_NULL(mSpellOptions, cleanup1);
|
||||
mSpellCheck = (SpellCheck_fn ) GetProcAddress(mLibrary, "SpellCheck" ); CHECK_NULL(mSpellCheck, cleanup1);
|
||||
mSpellTerminate = (SpellTerminate_fn ) GetProcAddress(mLibrary, "SpellTerminate" ); CHECK_NULL(mSpellTerminate, cleanup1);
|
||||
mSpellOpenMdr = (SpellOpenMdr_fn ) GetProcAddress(mLibrary, "SpellOpenMdr" ); CHECK_NULL(mSpellOpenMdr, cleanup1);
|
||||
mSpellCloseMdr = (SpellCloseMdr_fn ) GetProcAddress(mLibrary, "SpellCloseMdr" ); CHECK_NULL(mSpellCloseMdr, cleanup1);
|
||||
mSpellOpenUdr = (SpellOpenUdr_fn ) GetProcAddress(mLibrary, "SpellOpenUdr" ); CHECK_NULL(mSpellOpenUdr, cleanup1);
|
||||
mSpellAddUdr = (SpellAddUdr_fn ) GetProcAddress(mLibrary, "SpellAddUdr" ); CHECK_NULL(mSpellAddUdr, cleanup1);
|
||||
mSpellCloseUdr = (SpellCloseUdr_fn ) GetProcAddress(mLibrary, "SpellCloseUdr" ); CHECK_NULL(mSpellCloseUdr, cleanup1);
|
||||
mSpellAddChangeUdr = (SpellAddChangeUdr_fn) GetProcAddress(mLibrary, "SpellAddChangeUdr"); CHECK_NULL(mSpellAddChangeUdr, cleanup1);
|
||||
mSpellDelUdr = (SpellDelUdr_fn ) GetProcAddress(mLibrary, "SpellDelUdr" ); CHECK_NULL(mSpellDelUdr, cleanup1);
|
||||
mSpellClearUdr = (SpellClearUdr_fn ) GetProcAddress(mLibrary, "SpellClearUdr" ); CHECK_NULL(mSpellClearUdr, cleanup1);
|
||||
mSpellGetSizeUdr = (SpellGetSizeUdr_fn ) GetProcAddress(mLibrary, "SpellGetSizeUdr" ); CHECK_NULL(mSpellGetSizeUdr, cleanup1);
|
||||
mSpellGetListUdr = (SpellGetListUdr_fn ) GetProcAddress(mLibrary, "SpellGetListUdr" ); CHECK_NULL(mSpellGetListUdr, cleanup1);
|
||||
mSpellVerifyMdr = (SpellVerifyMdr_fn ) GetProcAddress(mLibrary, "SpellVerifyMdr" ); CHECK_NULL(mSpellVerifyMdr, cleanup1);
|
||||
|
||||
memset(&mSIB, 0, sizeof(mSIB));
|
||||
memset(&mSRB, 0, sizeof(mSRB));
|
||||
memset(&mMDRS, 0, sizeof(mMDRS));
|
||||
mSLID = mUDR = 0;
|
||||
|
||||
SEC sec;
|
||||
|
||||
// word w1, w2, w3;
|
||||
// mSpellVer(&w1, &w2, &w3);
|
||||
|
||||
WSC wsc;
|
||||
memset(&wsc, 0, sizeof(wsc));
|
||||
sec = mSpellInit(&mSLID, &wsc);
|
||||
CHECK_SEC(cleanup1);
|
||||
|
||||
sec = mSpellOpenMdr(mSLID, mDictionary, 0, 0, 1, mLIDC, &mMDRS);
|
||||
CHECK_SEC(cleanup2);
|
||||
|
||||
mSIB.cMdr = 1;
|
||||
mSIB.lrgMdr = &mMDRS.mdr;
|
||||
|
||||
sec = mSpellOptions(mSLID, SC_SO_SuggestFromUserDict|SC_SO_IgnoreAllCaps|SC_SO_IgnoreMixedDigits|SC_SO_IgnoreRomanNumerals|SC_SO_RateSuggestions);
|
||||
CHECK_SEC(cleanup2);
|
||||
|
||||
if (userdic)
|
||||
{
|
||||
BOOL ronly = FALSE;
|
||||
sec = mSpellOpenUdr(mSLID, (char*)userdic, TRUE, 0xfffe, &mUDR, &ronly);
|
||||
|
||||
if ((sec & 0xFF) == SC_SEC_NoErrors)
|
||||
{
|
||||
mSIB.cUdr = 1;
|
||||
mSIB.lrgUdr = &mUDR;
|
||||
}
|
||||
}
|
||||
|
||||
result = true;
|
||||
goto cleanup0;
|
||||
|
||||
cleanup2:
|
||||
mSpellTerminate(mSLID, TRUE);
|
||||
cleanup1:
|
||||
FreeLibrary(mLibrary);
|
||||
mLibrary = NULL;
|
||||
cleanup0:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CSpellLang::UnLoad()
|
||||
{
|
||||
if (!mLibrary) return;
|
||||
|
||||
if (mSIB.cUdr) mSpellCloseUdr(mSLID, mUDR, TRUE);
|
||||
if (mSIB.cMdr) mSpellCloseMdr(mSLID, &mMDRS);
|
||||
|
||||
FreeLibrary(mLibrary);
|
||||
mLibrary = NULL;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
bool CSpellLang::SpellCheck(const char *text)
|
||||
{
|
||||
if (!IsLoaded()) return true;
|
||||
|
||||
mSIB.wSpellState = 0;
|
||||
mSIB.lrgChr = (char*)text;
|
||||
mSIB.cChr = strlen(text);
|
||||
|
||||
mSRB.cChr = sizeof(mSZ);
|
||||
mSRB.cbRate = sizeof(mRate);
|
||||
mSRB.lrgSZ = mSZ;
|
||||
mSRB.lrgbRate = mRate;
|
||||
|
||||
SEC error = mSpellCheck(mSLID, SC_SCCC_VerifyBuffer, &mSIB, &mSRB);
|
||||
if (error & 0xFF) return false;
|
||||
|
||||
return mSRB.scrs == SC_SRCS_NoErrors;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
bool CSpellLang::SpellSuggest(const char *text, bool more)
|
||||
{
|
||||
if (!IsLoaded()) return false;
|
||||
|
||||
mSIB.wSpellState = 0;
|
||||
mSIB.lrgChr = (char*)text;
|
||||
mSIB.cChr = strlen(text);
|
||||
|
||||
mSRB.cChr = sizeof(mSZ);
|
||||
mSRB.cbRate = sizeof(mRate);
|
||||
mSRB.lrgSZ = mSZ;
|
||||
mSRB.lrgbRate = mRate;
|
||||
|
||||
SEC error = mSpellCheck(mSLID, more ? SC_SCCC_SuggestMore : SC_SCCC_Suggest, &mSIB, &mSRB);
|
||||
if (error & 0xFF) return false;
|
||||
|
||||
return mSRB.scrs == SC_SRCS_NoErrors;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
bool CSpellLang::AddWord(const char *text)
|
||||
{
|
||||
if (!IsLoaded()) return false;
|
||||
SEC error = mSpellAddUdr(mSLID, mUDR, (char*)text);
|
||||
return (error & 0xFF) == 0;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
CSpellChecker::CSpellChecker()
|
||||
{
|
||||
mInited = false;
|
||||
mLang = NULL;
|
||||
mText[0] = 0;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
bool CSpellChecker::Init()
|
||||
{
|
||||
int error;
|
||||
unsigned long index = 0;
|
||||
|
||||
HKEY hKeyPTools;
|
||||
HKEY hKeySpelling;
|
||||
|
||||
error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, SC_RKEY_Prooftools, 0, KEY_READ, &hKeyPTools);
|
||||
CHECK_ERROR(cleanup0);
|
||||
|
||||
error = RegOpenKeyEx(hKeyPTools, SC_RKEY_Spelling, 0, KEY_READ, &hKeySpelling);
|
||||
CHECK_ERROR(cleanup1);
|
||||
|
||||
do
|
||||
{
|
||||
char name[1024];
|
||||
unsigned long nsize = sizeof(name);
|
||||
|
||||
error = RegEnumKeyEx(hKeySpelling, index, name, &nsize, NULL, NULL, NULL, NULL);
|
||||
if (error == ERROR_SUCCESS)
|
||||
{
|
||||
strcat(name, "\\Normal");
|
||||
AddLanguage(hKeySpelling, name);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
while (error != ERROR_NO_MORE_ITEMS);
|
||||
|
||||
RegCloseKey(hKeySpelling);
|
||||
cleanup1:
|
||||
RegCloseKey(hKeyPTools);
|
||||
cleanup0:
|
||||
return mInited = (mLangs.size() > 0);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CSpellChecker::Close()
|
||||
{
|
||||
if (!IsInited()) return;
|
||||
mLangs.clear();
|
||||
mInited = false;
|
||||
mLang = NULL;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
bool CSpellChecker::Load(word lic, const char *userdic)
|
||||
{
|
||||
if (!IsInited()) return false;
|
||||
|
||||
std::vector<CSpellLang>::iterator it;
|
||||
for (it = mLangs.begin(); it != mLangs.end(); it++)
|
||||
{
|
||||
if ((it->GetLangCode() == lic) && it->Load(userdic))
|
||||
{
|
||||
UnLoad();
|
||||
mLang = it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return IsLoaded();
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
void CSpellChecker::UnLoad()
|
||||
{
|
||||
if (!IsLoaded()) return;
|
||||
mLang->UnLoad();
|
||||
mLang = NULL;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
bool CSpellChecker::Check(const char *text)
|
||||
{
|
||||
if (!IsLoaded()) return true;
|
||||
|
||||
OemToChar(text, mText);
|
||||
return mLang->SpellCheck(mText);
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
CSpellSuggestV &CSpellChecker::Suggest()
|
||||
{
|
||||
mSuggest.clear();
|
||||
if (!IsLoaded()) return mSuggest;
|
||||
if (!mLang->SpellSuggest(mText, false)) return mSuggest;
|
||||
|
||||
bool flag = true;
|
||||
bool more = false;
|
||||
|
||||
for (int idx = 0; idx < mLang->mSRB.cChrMac; idx++)
|
||||
{
|
||||
if (mLang->mSZ[idx] == 0) { idx++; flag = true; }
|
||||
|
||||
if (flag && mLang->mSZ[idx])
|
||||
{
|
||||
flag = false;
|
||||
CharToOem(&mLang->mSZ[idx], &mLang->mSZ[idx]);
|
||||
mSuggest.push_back(std::pair<byte, std::string>(0, " " + std::string(&mLang->mSZ[idx]) + char(' ')));
|
||||
}
|
||||
else if (!more && !mLang->mSZ[idx])
|
||||
{
|
||||
more = true;
|
||||
|
||||
if (!mLang->SpellSuggest(mText, more = true))
|
||||
return mSuggest;
|
||||
else
|
||||
{
|
||||
flag = true;
|
||||
idx = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mSuggest;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#undef CHECK_ERROR
|
||||
#undef CHECK_NULL
|
||||
#undef CHECK_SEC
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#endif // #if defined(__WIN32__)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#endif // #if defined(__GOLD_SPELL__)
|
||||
|
||||
// ------------------------------------------------------------------
|
235
goldlib/gall/gespell.h
Normal file
235
goldlib/gall/gespell.h
Normal file
@ -0,0 +1,235 @@
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// GoldED+
|
||||
// Copyright (C) 1990-1999 Odinn Sorensen
|
||||
// Copyright (C) 1999-2000 Alexander S. Aganichev
|
||||
// ------------------------------------------------------------------
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
// MA 02111-1307 USA
|
||||
// ------------------------------------------------------------------
|
||||
// $Id$
|
||||
// ------------------------------------------------------------------
|
||||
// SpellChecker Structures and Classes.
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#ifndef __GESPELL_H__
|
||||
#define __GESPELL_H__
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__GOLD_SPELL__)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#if defined(__WIN32__)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
typedef uint32_t MDR; // Main Dictionary Reference
|
||||
typedef uint32_t UDR; // User Dictionary Reference
|
||||
typedef uint16_t SEC; // Spell Error Code
|
||||
typedef uint16_t LIDC; // Language Identifier Code
|
||||
typedef uint16_t SCCC; // Spell Check Command Code
|
||||
typedef uint32_t SLID; // Spell Id type
|
||||
typedef uint16_t SCIS; // Spell Check Input Status
|
||||
typedef uint16_t SCRS; // Spell Check Return Status
|
||||
|
||||
typedef struct WizSpecChars
|
||||
{
|
||||
byte bIgnore;
|
||||
byte bHyphenHard;
|
||||
byte bHyphenSoft;
|
||||
byte bHyphenNonBreaking;
|
||||
byte bEmDash;
|
||||
byte bEnDash;
|
||||
byte bEllipsis;
|
||||
byte rgLineBreak[2];
|
||||
byte rgParaBreak[2];
|
||||
} WSC;
|
||||
|
||||
typedef struct SpellInputBuffer
|
||||
{
|
||||
word cChr; // Total characters in buffer area
|
||||
word cMdr; // Count of MDR's specified in lrgMdr
|
||||
word cUdr; // Count of UDR's specified in lrgUdr
|
||||
word wSpellState; // State relative to previous SpellCheck call
|
||||
char *lrgChr; // Pointer to text to be spell checked
|
||||
MDR *lrgMdr; // List of main dicts to use when spelling the buffer
|
||||
UDR *lrgUdr; // List of user dicts to use when spelling the buffer
|
||||
} SIB;
|
||||
|
||||
typedef struct SpellReturnBuffer
|
||||
{
|
||||
// These fields are set by the SpellCheck() function
|
||||
word iChrErr; // Position in the SIB
|
||||
word cChrErr; // Length of error "word" in SIB
|
||||
SCRS scrs; // Spell check return status
|
||||
word cSZ; // Count of sz's put in buffer
|
||||
word cChrMac; // Current total of chars in buffer
|
||||
|
||||
// These fields MUST be set by the app, NULL pointers are invalid
|
||||
word cChr; // Total space in lrgSZ
|
||||
char *lrgSZ; // Ptr to alternatives format: word\0word\0...word\0\0
|
||||
byte *lrgbRate; // Ptr to Rating value for each suggest returned
|
||||
word cbRate; // Number of elements in lrgbRate
|
||||
} SRB;
|
||||
|
||||
typedef struct mdrs
|
||||
{
|
||||
MDR mdr;
|
||||
LIDC lidc;
|
||||
UDR udr;
|
||||
} MDRS;
|
||||
|
||||
typedef SEC (*SpellVer_fn ) (word*, word*, word*);
|
||||
typedef SEC (*SpellInit_fn ) (SLID*, WSC*);
|
||||
typedef SEC (*SpellOptions_fn ) (SLID, dword);
|
||||
typedef SEC (*SpellCheck_fn ) (SLID, SCCC, SIB*, SRB*);
|
||||
typedef SEC (*SpellTerminate_fn ) (SLID, BOOL);
|
||||
typedef SEC (*SpellOpenMdr_fn ) (SLID, char*, char*, BOOL, BOOL, LIDC, MDRS*);
|
||||
typedef SEC (*SpellCloseMdr_fn ) (SLID, MDRS*);
|
||||
typedef SEC (*SpellOpenUdr_fn ) (SLID, char*, BOOL, word, UDR*, BOOL*);
|
||||
typedef SEC (*SpellAddUdr_fn ) (SLID, UDR, char*);
|
||||
typedef SEC (*SpellCloseUdr_fn ) (SLID, UDR, BOOL);
|
||||
typedef SEC (*SpellAddChangeUdr_fn) (SLID, UDR, char*, char*);
|
||||
typedef SEC (*SpellDelUdr_fn ) (SLID, UDR, char*);
|
||||
typedef SEC (*SpellClearUdr_fn ) (SLID, UDR);
|
||||
typedef SEC (*SpellGetSizeUdr_fn ) (SLID, UDR, word*);
|
||||
typedef SEC (*SpellGetListUdr_fn ) (SLID, UDR, word, SRB*);
|
||||
typedef SEC (*SpellVerifyMdr_fn ) (char*, LIDC, LIDC*);
|
||||
|
||||
class CSpellLang
|
||||
{
|
||||
friend class CSpellChecker;
|
||||
|
||||
private:
|
||||
LIDC mLIDC;
|
||||
SLID mSLID;
|
||||
MDRS mMDRS;
|
||||
UDR mUDR;
|
||||
SIB mSIB;
|
||||
SRB mSRB;
|
||||
|
||||
char mSZ[1024];
|
||||
byte mRate[1024];
|
||||
|
||||
char mEngine[_MAX_PATH];
|
||||
char mDictionary[_MAX_PATH];
|
||||
|
||||
HINSTANCE mLibrary;
|
||||
|
||||
SpellVer_fn mSpellVer;
|
||||
SpellInit_fn mSpellInit;
|
||||
SpellOptions_fn mSpellOptions;
|
||||
SpellCheck_fn mSpellCheck;
|
||||
SpellTerminate_fn mSpellTerminate;
|
||||
SpellOpenMdr_fn mSpellOpenMdr;
|
||||
SpellCloseMdr_fn mSpellCloseMdr;
|
||||
SpellOpenUdr_fn mSpellOpenUdr;
|
||||
SpellAddUdr_fn mSpellAddUdr;
|
||||
SpellCloseUdr_fn mSpellCloseUdr;
|
||||
SpellAddChangeUdr_fn mSpellAddChangeUdr;
|
||||
SpellDelUdr_fn mSpellDelUdr;
|
||||
SpellClearUdr_fn mSpellClearUdr;
|
||||
SpellGetSizeUdr_fn mSpellGetSizeUdr;
|
||||
SpellGetListUdr_fn mSpellGetListUdr;
|
||||
SpellVerifyMdr_fn mSpellVerifyMdr;
|
||||
|
||||
public:
|
||||
CSpellLang() { mLibrary = NULL; }
|
||||
~CSpellLang() { Close(); }
|
||||
|
||||
bool Init(HKEY hKey, const char *name);
|
||||
void Close() { UnLoad(); }
|
||||
|
||||
bool Load(const char *userdic);
|
||||
void UnLoad();
|
||||
|
||||
bool SpellCheck(const char *text);
|
||||
bool SpellSuggest(const char *text, bool more);
|
||||
bool AddWord(const char *text);
|
||||
|
||||
LIDC GetLangCode() { return mLIDC; }
|
||||
|
||||
bool IsLoaded() { return mLibrary != NULL; }
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector< std::pair<byte, std::string> > CSpellSuggestV;
|
||||
typedef std::vector<CSpellLang> CSpellLangV;
|
||||
|
||||
class CSpellChecker
|
||||
{
|
||||
private:
|
||||
bool mInited;
|
||||
char mText[1024];
|
||||
|
||||
CSpellLang *mLang;
|
||||
CSpellLangV mLangs;
|
||||
CSpellSuggestV mSuggest;
|
||||
|
||||
private:
|
||||
void AddLanguage(HKEY hKey, const char *name)
|
||||
{
|
||||
CSpellLang lang;
|
||||
|
||||
if (lang.Init(hKey, name))
|
||||
mLangs.push_back(lang);
|
||||
}
|
||||
|
||||
public:
|
||||
CSpellChecker();
|
||||
~CSpellChecker() { Close(); }
|
||||
|
||||
bool Init();
|
||||
void Close();
|
||||
|
||||
bool Load(word lic, const char *userdic = NULL);
|
||||
void UnLoad();
|
||||
|
||||
bool Check(const char *text);
|
||||
CSpellSuggestV &Suggest();
|
||||
|
||||
bool Check(std::string &text) { return Check(text.c_str()); }
|
||||
bool AddWord() { return IsLoaded() ? mLang->AddWord(mText) : false; };
|
||||
|
||||
CSpellSuggestV &GetSuggest() { return mSuggest; }
|
||||
CSpellLangV &GetLangs() { return mLangs; }
|
||||
LIDC GetLangCode() { return IsLoaded() ? mLang->GetLangCode() : 0xFFFF; }
|
||||
|
||||
bool IsInited() { return mInited; }
|
||||
bool IsLoaded() { return mLang != NULL; }
|
||||
};
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#endif //#if defined(__WIN32__)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#endif //#if defined(__GOLD_SPELL__)
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#endif //#ifndef __GESPELL_H__
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
Reference in New Issue
Block a user