ide: Spellchecking comments

git-svn-id: svn://ultimatepp.org/upp/trunk@10384 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2016-10-30 10:41:05 +00:00
parent 68b953002b
commit 62d921fcb0
26 changed files with 443 additions and 320 deletions

View file

@ -89,16 +89,23 @@ const wchar *HighlightNumber(HighlightOutput& hls, const wchar *p, bool ts, bool
const wchar *CSyntax::DoComment(HighlightOutput& hls, const wchar *p, const wchar *e)
{
String w;
for(const wchar *s = p; s < e && IsAlpha(*s) && w.GetCount() < 5; s++)
WString w;
for(const wchar *s = p; s < e && IsLetter(*s); s++)
w.Cat(ToUpper(*s));
int n = w.GetCount();
if(findarg(w, "TODO", "FIXME") >= 0)
if(!n)
for(const wchar *s = p; s < e && !IsLetter(*s); s++)
n++;
word flags = 0;
if(n && comments_lang && !SpellWord(w, comments_lang))
flags = LineEdit::SPELLERROR;
hls.SetFlags(n, flags);
static WString todo = "TODO";
static WString fixme = "FIXME";
if(w.GetCount() >= 4 && w.GetCount() <= 5 && findarg(w, todo, fixme) >= 0)
hls.Put(n, hl_style[INK_COMMENT_WORD], hl_style[PAPER_COMMENT_WORD]);
else {
n = max(n, 1);
else
hls.Put(n, hl_style[INK_COMMENT]);
}
return p + n;
}

View file

@ -41,7 +41,7 @@ protected:
static int InitUpp(const char **q);
static void InitKeywords();
static const wchar *DoComment(HighlightOutput& hls, const wchar *p, const wchar *e);
const wchar *DoComment(HighlightOutput& hls, const wchar *p, const wchar *e);
static Vector< Index<String> > keyword;
static Vector< Index<String> > name;

View file

@ -17,6 +17,7 @@ One<EditorSyntax> CodeEditor::GetSyntax(int line)
{
CTIMING("GetSyntax");
One<EditorSyntax> syntax = EditorSyntax::Create(highlight);
syntax->SpellCheckComments(spellcheck_comments);
int ln = 0;
for(int i = 0; i < __countof(syntax_cache); i++)
if(line >= syntax_cache[i].line && syntax_cache[i].line > 0) {

View file

@ -274,6 +274,8 @@ protected:
String highlight;
int spellcheck_comments = 0;
struct Tip : Ctrl {
Value v;
const Display *d;
@ -462,6 +464,9 @@ public:
void IndentAmount(int ia) { indent_amount = ia; }
void NoParenthesisIndent(bool b) { no_parenthesis_indent = b; }
void SpellcheckComments(int lang) { spellcheck_comments = lang; Refresh(); }
int GetSpellcheckComments() const { return spellcheck_comments; }
void NoFindReplace() { withfindreplace = false; }
void LineNumbers(bool b) { bar.LineNumbers(b); }

View file

@ -59,6 +59,14 @@ void HighlightOutput::SetPaper(int pos, int count, Color paper)
v[pos++].paper = paper;
}
void HighlightOutput::SetFlags(int pos, int count, word flags)
{
if(pos + count > v.GetCount())
v.At(pos + count - 1, def);
while(count-- > 0)
v[pos++].flags = flags;
}
void HighlightOutput::SetInk(int pos, int count, Color ink)
{
if(pos + count > v.GetCount())

View file

@ -72,13 +72,16 @@ struct HighlightOutput : HighlightSetup {
public:
void SetChar(int pos, int chr) { v[pos].chr = chr; }
void Set(int pos, int count, const HlStyle& ink);
void SetFlags(int pos, int count, word flags);
void SetFont(int pos, int count, const HlStyle& f);
void SetPaper(int pos, int count, Color paper);
void SetInk(int pos, int count, Color ink);
void SetFlags(int count, word flags) { SetFlags(pos, count, flags); }
void Put(int count, const HlStyle& ink) { Set(pos, count, ink); pos += count; }
void Put(int count, const HlStyle& ink, const HlStyle& paper);
void Put(const HlStyle& ink) { Put(1, ink); }
void Put(const HlStyle& ink, word flags) { Put(1, ink); v[pos - 1].flags = flags; }
void Flags(word flags) { v[pos - 1].flags = flags; }
int GetCount() const { return v.GetCount(); }
const wchar *CString(const wchar *p);
@ -98,6 +101,7 @@ class EditorSyntax : public HighlightSetup { // Inheriting to make static member
protected:
bool ignore_errors;
int comments_lang;
public:
virtual void Clear();
@ -118,6 +122,7 @@ public:
String Get() { CTIMING("Get"); return StoreAsString(*this); }
void IgnoreErrors() { ignore_errors = true; }
void SpellCheckComments(int lang) { comments_lang = lang; }
EditorSyntax() { Clear(); ignore_errors = false; }

View file

@ -179,6 +179,11 @@ String ConfigFile(const char *file) {
#endif//PLATFORM
}
String GetConfigFolder()
{
return GetFileFolder(ConfigFile("x"));
}
String ConfigFile() {
return ConfigFile(GetExeTitle() + ".cfg");
}

View file

@ -16,6 +16,7 @@ void SetHomeDirectory(const char *dir);
void UseHomeDirectoryConfig(bool b = true);
String GetConfigFolder();
String ConfigFile(const char *file);
String ConfigFile();

View file

@ -83,6 +83,7 @@ file
Util.cpp,
mathutil.cpp,
Random.cpp,
Speller.cpp,
LocalProcess.h,
LocalProcess.cpp,
Containers readonly separator,

288
uppsrc/Core/Speller.cpp Normal file
View file

@ -0,0 +1,288 @@
#include "Core.h"
namespace Upp {
#define LLOG(x) // LOG(x)
struct SpellBlock : Moveable<SpellBlock> {
String first;
int offset;
int ctrl_len;
int text_len;
};
struct Speller {
String data;
byte charset;
const char *voc[256];
int dict;
struct Line : Moveable<Line> {
const byte *begin;
const byte *end;
};
VectorMap<dword, Line> line;
Index<WString> user;
String path;
Array<SpellBlock> block;
bool SetOld(const String& data);
void Clear() { data.Clear(); path.Clear(); }
operator bool() const { return !data.IsEmpty() || path.GetCount(); }
bool CheckOld(const WString& wstr) const;
String Get(int offset, int len);
};
bool Speller::SetOld(const String& _data)
{
data = _data;
const char *s = data;
if(s >= data.End()) {
data.Clear();
return false;
}
charset = *s++;
s++;// reserved for prefixes
dict = *s++;
for(int i = 0; i < 256 - dict; i++) {
if(s >= data.End()) {
data.Clear();
return false;
}
voc[i] = s;
while(*s) s++;
s++;
}
line.Clear();
while(s < data.End()) {
if(s + 8 >= data.End()) {
data.Clear();
return false;
}
int code = Peek32le(s);
s += 4;
int len = Peek32le(s);
s += 4;
Line& l = line.Add(code);
l.begin = (const byte *)s;
s += len;
l.end = (const byte *)s;
};
return true;
}
bool Speller::CheckOld(const WString& wstr) const
{
int len = wstr.GetLength();
if(len < 2)
return true;
if(len < 64) {
String w = FromUnicode(wstr, charset);
String wl = FromUnicode(ToLower(wstr), charset);
int i;
if(len == 2) {
w.Cat(127);
wl.Cat(127);
}
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;
String q;
while(s < e)
if(*s < dict) {
if(q == w || q == wl)
return true;
q.Trim(*s++);
}
else {
ASSERT(*s >= dict);
const char *x = voc[(int)*s++ - dict];
q.Cat(x);
}
if(q == w || q == wl)
return true;
}
}
return user.Find(wstr) >= 0;;
}
static String sUserFile(int lang)
{
return ConfigFile(LNGAsText(lang) + ".usp");
}
String spell_path;
void SetSpellPath(const String& p)
{
spell_path = p;
}
static String sZet(FileIn& in, int offset, int len)
{
in.Seek(offset);
return ZDecompress(in.Get(len));
}
void DoSpellerPath(String& pp, String dir)
{
for(;;) {
pp << dir << ';';
String d = GetFileFolder(dir);
if(d == dir) break;
dir = d;
}
}
Speller *sGetSpeller(int lang)
{
static ArrayMap<int, Speller> speller;
int q = speller.Find(lang);
if(q < 0) {
String pp = spell_path;
DoSpellerPath(pp, GetExeDirFile("scd"));
DoSpellerPath(pp, ConfigFile("scd"));
pp << spell_path << ';' << getenv("LIB") << ';' << getenv("PATH") << ';';
String path = GetFileOnPath(ToLower(LNGAsText(lang)) + ".udc", pp);
if(IsNull(path))
path = GetFileOnPath(ToLower(LNGAsText(lang)) + ".scd", pp);
if(IsNull(path))
return NULL;
FileIn in(path);
if(!in)
return NULL;
q = speller.GetCount();
Speller& f = speller.Add(lang);
FileIn user(sUserFile(lang));
while(!user.IsEof()) {
String s = user.GetLine();
if(!s.IsEmpty())
f.user.Add(FromUtf8(s));
}
if(in.Get() != 255)
f.SetOld(LoadFile(path));
else {
f.path = path;
int n = in.GetL();
LLOG("Found scd file " << path << " blocks " << n);
if(n > 0 && n < 100000) {
for(int i = 0; i < n; i++) {
SpellBlock& b = f.block.Add();
b.first = in.Get(in.Get());
b.ctrl_len = in.GetL();
b.text_len = in.GetL();
}
if(in.IsEof())
f.block.Clear();
else {
int off = (int)in.GetPos();
for(int i = 0; i < n; i++) {
SpellBlock& b = f.block[i];
b.offset = off;
off += b.ctrl_len + b.text_len;
}
}
}
}
}
return &speller[q];
}
bool SpellWordRaw(const WString& wrd, int lang, Vector<String> *withdia)
{
Speller *f = sGetSpeller(lang);
if(!f)
return true;
if(f->data.GetCount())
return f->CheckOld(wrd);
String awrd = ToUpper(ToAscii(wrd).ToString());
String t1 = ToUtf8(wrd);
String t2 = ToUtf8(ToLower(wrd));
for(int i = 0;; i++) {
if(i + 1 >= f->block.GetCount() || awrd <= f->block[i + 1].first) {
for(;;) {
if(i >= f->block.GetCount())
return f->user.Find(wrd) >= 0;;
LLOG("Spell block " << i << ": " << f->block[i].first);
const SpellBlock& b = f->block[i++];
if(b.first > awrd) {
LLOG(" --- end");
return f->user.Find(wrd) >= 0;;
}
FileIn in(f->path);
String ctrl = sZet(in, b.offset, b.ctrl_len);
String text = sZet(in, b.offset + b.ctrl_len, b.text_len);
in.Close();
String w;
const char *s = ctrl;
const char *e = ctrl.End();
const char *t = text;
const char *te = text.End();
while(s < e && t < te) {
w.Trim(*s++);
while(*t)
w.Cat(*t++);
if(w == t1 || w == t2)
return true;
if(withdia && t2 == ToLower(ToAscii(w.ToWString()).ToString()))
withdia->Add(w);
t++;
}
}
}
}
return f->user.Find(wrd) >= 0;;
}
struct SpellKey : Moveable<SpellKey> {
int lang;
WString wrd;
unsigned GetHashValue() const { return CombineHash(lang, wrd); }
bool operator==(const SpellKey& b) const { return lang == b.lang && wrd == b.wrd; }
};
struct SpellMaker : LRUCache<bool, SpellKey>::Maker {
SpellKey k;
SpellKey Key() const { return k; }
int Make(bool& r) const {
r = SpellWordRaw(k.wrd, k.lang);
return 1;
}
};
static LRUCache<bool, SpellKey> speller_cache;
bool SpellWord(const WString& ws, int lang)
{
speller_cache.Shrink(2000);
SpellMaker m;
m.k.lang = lang;
m.k.wrd = ws;
return speller_cache.Get(m);
}
bool SpellWord(const wchar *ws, int len, int lang)
{
return SpellWord(WString(ws, len), lang);
}
void SpellerAdd(const WString& w, int lang)
{
if(!SpellWord(w, w.GetCount(), lang)) {
Speller *f = sGetSpeller(lang);
if(f) {
FileAppend fa(sUserFile(lang));
fa.PutLine(ToUtf8(w));
f->user.Add(w);
speller_cache.Clear();
}
}
}
};

View file

@ -482,6 +482,11 @@ String Replace(const String& s, const VectorMap<String, String>& fr);
WString Replace(const WString& s, const Vector<WString>& find, const Vector<WString>& replace);
WString Replace(const WString& s, const VectorMap<WString, WString>& fr);
bool SpellWordRaw(const WString& wrd, int lang, Vector<String> *withdia = NULL);
bool SpellWord(const WString& ws, int lang);
bool SpellWord(const wchar *ws, int len, int lang);
void SpellerAdd(const WString& w, int lang);
String GetP7Signature(const void *data, int length, const String& cert_pem, const String& pkey_pem);
String GetP7Signature(const String& data, const String& cert_pem, const String& pkey_pem);
@ -500,4 +505,3 @@ String Garble(const String& s);
String Encode64(const String& s);
String Decode64(const String& s);

View file

@ -66,9 +66,8 @@ has ability to `'add`' functions using operator<<. Also, unlike
exception.&]
[s5; [* Event ]is equivalent of Callback `- unlike Callback, it is
not necessary to have Callback, Callback1, Callback2, number
of parameters is resolved by C`+`+11 template varargs. For backward
compatibility Callback`[N`] are aliased as Event variants.&]
[s5; Similarly, [* EventGate] is a new equivalent of [* Gate].&]
of parameters is resolved by C`+`+11 template varargs.&]
[s5; Callback is deprecated but supported for backward compatibility.&]
[s3; Algorithms and Containers&]
[s5; The set of algorithms provided by U`+`+ is now streamlined by
introduction of [/ Range] concept. Range is entity that provides

View file

@ -461,7 +461,7 @@ void LineEdit::Paint0(Draw& w) {
else
ln = tx.GetCount();
int lgp = -1;
for(int pass = 0; pass < 2; pass++) {
for(int pass = 0; pass < 3; pass++) {
int gp = 0;
int scx = fsz.cx * sc.x;
sOptimizedRectRenderer rw(w);
@ -546,7 +546,9 @@ void LineEdit::Paint0(Draw& w) {
if(bordercolumn > 0 && bordercolumn >= gp && bordercolumn < gp + 1 + cjk)
rw.DrawRect((bordercolumn - sc.x) * fsz.cx, y, 1, fsz.cy, bordercolor);
}
else
if(pass == 1 && (h.flags & SPELLERROR))
rw.DrawRect(x, max(y, y + fsz.cy - Zy(1)), (cjk + 1) * fsz.cx, Zy(1), LtRed());
if(pass == 2)
tw.DrawChar(x + (h.flags & SHIFT_L ? -fsz.cx / 6 : h.flags & SHIFT_R ? fsz.cx / 6 : 0),
y + fascent - h.font.GetAscent(),
h.chr, (cjk + 1) * fsz.cx, h.font, h.ink);

View file

@ -243,6 +243,7 @@ public:
enum Flags {
SHIFT_L = 1,
SHIFT_R = 2,
SPELLERROR = 4,
};
struct Highlight : Moveable<Highlight> {

View file

@ -197,10 +197,6 @@ public:
StyleManager();
};
bool SpellWordRaw(const WString& wrd, int lang, Vector<String> *withdia = NULL);
bool SpellWord(const wchar *ws, int len, int lang);
bool SpellWord(const WString& ws, int lang);
void SetupFaceList(DropList& face);
class RichEdit : public Ctrl, private TextArrayOps {

View file

@ -2,287 +2,9 @@
namespace Upp {
#define LLOG(x) // LOG(x)
struct SpellBlock : Moveable<SpellBlock> {
String first;
int offset;
int ctrl_len;
int text_len;
};
struct Speller {
String data;
byte charset;
const char *voc[256];
int dict;
struct Line : Moveable<Line> {
const byte *begin;
const byte *end;
};
VectorMap<dword, Line> line;
Index<WString> user;
String path;
Array<SpellBlock> block;
bool SetOld(const String& data);
void Clear() { data.Clear(); path.Clear(); }
operator bool() const { return !data.IsEmpty() || path.GetCount(); }
bool CheckOld(const WString& wstr) const;
String Get(int offset, int len);
};
bool Speller::SetOld(const String& _data)
{
data = _data;
const char *s = data;
if(s >= data.End()) {
data.Clear();
return false;
}
charset = *s++;
s++;// reserved for prefixes
dict = *s++;
for(int i = 0; i < 256 - dict; i++) {
if(s >= data.End()) {
data.Clear();
return false;
}
voc[i] = s;
while(*s) s++;
s++;
}
line.Clear();
while(s < data.End()) {
if(s + 8 >= data.End()) {
data.Clear();
return false;
}
int code = Peek32le(s);
s += 4;
int len = Peek32le(s);
s += 4;
Line& l = line.Add(code);
l.begin = (const byte *)s;
s += len;
l.end = (const byte *)s;
};
return true;
}
bool Speller::CheckOld(const WString& wstr) const
{
int len = wstr.GetLength();
if(len == 1)
return true;
if(len < 64) {
String w = FromUnicode(wstr, charset);
String wl = FromUnicode(ToLower(wstr), charset);
int i;
if(len == 2) {
w.Cat(127);
wl.Cat(127);
}
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;
String q;
while(s < e)
if(*s < dict) {
if(q == w || q == wl)
return true;
q.Trim(*s++);
}
else {
ASSERT(*s >= dict);
const char *x = voc[(int)*s++ - dict];
q.Cat(x);
}
if(q == w || q == wl)
return true;
}
}
return user.Find(wstr) >= 0;;
}
static String sUserFile(int lang)
{
return ConfigFile(LNGAsText(lang) + ".usp");
}
String spell_path;
void SetSpellPath(const String& p)
{
spell_path = p;
}
static String sZet(FileIn& in, int offset, int len)
{
in.Seek(offset);
return ZDecompress(in.Get(len));
}
void DoSpellerPath(String& pp, String dir)
{
for(;;) {
pp << dir << ';';
String d = GetFileFolder(dir);
if(d == dir) break;
dir = d;
}
}
Speller *sGetSpeller(int lang)
{
static ArrayMap<int, Speller> speller;
int q = speller.Find(lang);
if(q < 0) {
String pp = spell_path;
DoSpellerPath(pp, GetExeDirFile("scd"));
DoSpellerPath(pp, ConfigFile("scd"));
pp << spell_path << ';' << getenv("LIB") << ';' << getenv("PATH") << ';';
String path = GetFileOnPath(ToLower(LNGAsText(lang)) + ".udc", pp);
if(IsNull(path))
path = GetFileOnPath(ToLower(LNGAsText(lang)) + ".scd", pp);
if(IsNull(path))
return NULL;
FileIn in(path);
if(!in)
return NULL;
q = speller.GetCount();
Speller& f = speller.Add(lang);
FileIn user(sUserFile(lang));
while(!user.IsEof()) {
String s = user.GetLine();
if(!s.IsEmpty())
f.user.Add(FromUtf8(s));
}
if(in.Get() != 255)
f.SetOld(LoadFile(path));
else {
f.path = path;
int n = in.GetL();
LLOG("Found scd file " << path << " blocks " << n);
if(n > 0 && n < 100000) {
for(int i = 0; i < n; i++) {
SpellBlock& b = f.block.Add();
b.first = in.Get(in.Get());
b.ctrl_len = in.GetL();
b.text_len = in.GetL();
}
if(in.IsEof())
f.block.Clear();
else {
int off = (int)in.GetPos();
for(int i = 0; i < n; i++) {
SpellBlock& b = f.block[i];
b.offset = off;
off += b.ctrl_len + b.text_len;
}
}
}
}
}
return &speller[q];
}
bool SpellWordRaw(const WString& wrd, int lang, Vector<String> *withdia)
{
Speller *f = sGetSpeller(lang);
if(!f)
return true;
if(f->data.GetCount())
return f->CheckOld(wrd);
String awrd = ToUpper(ToAscii(wrd).ToString());
String t1 = ToUtf8(wrd);
String t2 = ToUtf8(ToLower(wrd));
for(int i = 0;; i++) {
if(i + 1 >= f->block.GetCount() || awrd <= f->block[i + 1].first) {
for(;;) {
if(i >= f->block.GetCount())
return f->user.Find(wrd) >= 0;;
LLOG("Spell block " << i << ": " << f->block[i].first);
const SpellBlock& b = f->block[i++];
if(b.first > awrd) {
LLOG(" --- end");
return f->user.Find(wrd) >= 0;;
}
FileIn in(f->path);
String ctrl = sZet(in, b.offset, b.ctrl_len);
String text = sZet(in, b.offset + b.ctrl_len, b.text_len);
in.Close();
String w;
const char *s = ctrl;
const char *e = ctrl.End();
const char *t = text;
const char *te = text.End();
while(s < e && t < te) {
w.Trim(*s++);
while(*t)
w.Cat(*t++);
if(w == t1 || w == t2)
return true;
if(withdia && t2 == ToLower(ToAscii(w.ToWString()).ToString()))
withdia->Add(w);
t++;
}
}
}
}
return f->user.Find(wrd) >= 0;;
}
struct SpellKey : Moveable<SpellKey> {
int lang;
WString wrd;
unsigned GetHashValue() const { return CombineHash(lang, wrd); }
bool operator==(const SpellKey& b) const { return lang == b.lang && wrd == b.wrd; }
};
struct SpellMaker : LRUCache<bool, SpellKey>::Maker {
SpellKey k;
SpellKey Key() const { return k; }
int Make(bool& r) const {
r = SpellWordRaw(k.wrd, k.lang);
return 1;
}
};
static LRUCache<bool, SpellKey> speller_cache;
bool SpellWord(const WString& ws, int lang)
{
speller_cache.Shrink(2000);
SpellMaker m;
m.k.lang = lang;
m.k.wrd = ws;
return speller_cache.Get(m);
}
bool SpellWord(const wchar *ws, int len, int lang)
{
return SpellWord(WString(ws, len), lang);
}
void RichEdit::SpellerAdd(const WString& w, int lang)
{
if(!SpellWord(w, w.GetCount(), lang)) {
Speller *f = sGetSpeller(lang);
if(f) {
FileAppend fa(sUserFile(lang));
fa.PutLine(ToUtf8(w));
f->user.Add(w);
speller_cache.Clear();
}
}
Upp::SpellerAdd(w, lang);
}
int RichEdit::fixedlang;

View file

@ -162,7 +162,7 @@ void Sentinel(Stream& s, const char *txt)
void Ide::Serialize(Stream& s)
{
int version = 10;
int version = 11;
Sentinel(s, "before 12341234");
s.Magic(0x12341234);
Sentinel(s, "after magic");
@ -200,6 +200,8 @@ void Ide::Serialize(Stream& s)
s % tabs_grouping;
s % tabs_serialize;
s % tabs_stacking;
if(version >= 11)
s % spellcheck_comments;
bool dummy_force_crlf = false;
s % dummy_force_crlf;
if(version >= 1)

View file

@ -302,10 +302,11 @@ public:
int font;
String highlight;
bool pch, nopch, noblitz;
int spellcheck_comments;
void operator=(const String& s) { String::operator=(s); readonly = separator = false; }
void Init() { readonly = separator = false; tabsize = Null; charset = 0; font = 0;
pch = nopch = noblitz = false; }
pch = nopch = noblitz = false; spellcheck_comments = Null; }
File() { Init(); }
File(const String& s) : String(s) { Init(); }
@ -334,6 +335,7 @@ public:
Time time;
bool bold, italic;
Color ink;
int spellcheck_comments;
int GetCount() const { return file.GetCount(); }
File& operator[](int i) { return file[i]; }

View file

@ -163,6 +163,7 @@ void Package::Reset()
noblitz = nowarnings = false;
bold = italic = false;
ink = Null;
spellcheck_comments = Null;
}
Package::Package()
@ -319,6 +320,9 @@ bool Package::Load(const char *path)
else
if(p.Id("highlight"))
f.highlight = p.ReadId();
else
if(p.Id("spellcheck_comments"))
f.spellcheck_comments = LNGFromText(p.ReadString());
else
p.SkipTerm();
}
@ -348,6 +352,9 @@ bool Package::Load(const char *path)
else
if(p.Id("custom"))
custom.Add().Load(p);
else
if(p.Id("spellcheck_comments"))
spellcheck_comments = LNGFromText(p.ReadString());
else
p.SkipTerm();
}
@ -422,6 +429,12 @@ String IdeCharsetName(byte charset) {
CharsetName(charset));
}
void PutSpellCheckComments(StringStream& out, int sc)
{
if(!IsNull(sc))
out << " spellcheck_comments " << AsCString(sc ? LNGAsText(sc) : "");
}
bool Package::Save(const char *path) const {
StringStream out;
if(description.GetCount() || italic || bold || !IsNull(ink)) {
@ -475,6 +488,7 @@ bool Package::Save(const char *path) const {
out << " charset " << AsCString(IdeCharsetName(f.charset));
if(!IsNull(f.highlight))
out << " highlight " << f.highlight;
PutSpellCheckComments(out, f.spellcheck_comments);
putfopt(out, "options", f.option);
putfopt(out, "depends", f.depends);
}
@ -489,6 +503,7 @@ bool Package::Save(const char *path) const {
}
out << ";\n\n";
}
PutSpellCheckComments(out, spellcheck_comments);
for(int i = 0; i < custom.GetCount(); i++)
out << custom[i].AsString();
return SaveChangedFile(path, out.GetResult());

View file

@ -332,6 +332,32 @@ void InsertPath(EditString *es)
es->SetWantFocus();
}
void DlSpellerLangs(DropList& dl)
{
static Vector<int> lng;
ONCELOCK {
VectorMap<int, String> lngs;
String path = GetExeDirFile("scd") + ';' + ConfigFile("scd") + ';' +
GetExeFolder() + ';' + GetConfigFolder() + ';' +
getenv("LIB") + ';' + getenv("PATH");
Vector<String> p = Split(path, ';');
for(auto dir : p) {
FindFile ff(AppendFileName(dir, "*.scd"));
while(ff) {
int lang = LNGFromText(ff.GetName());
if(lang)
lngs.Add(lang, LNGAsText(lang));
ff.Next();
}
}
SortByValue(lngs);
lng = lngs.PickKeys();
}
dl.Add(0, "Off");
for(auto l : lng)
dl.Add(l, LNGAsText(l));
}
void Ide::SetupFormat() {
FormatDlg dlg;
dlg.Title("Settings");
@ -401,6 +427,9 @@ void Ide::SetupFormat() {
edt.indent_amount.Enable(indent_spaces);
CtrlRetriever rtvr;
int hs = hilite_scope;
DlSpellerLangs(edt.spellcheck_comments);
rtvr
(hlt.hilite_scope, hs)
(hlt.hilite_bracket, hilite_bracket)
@ -427,6 +456,7 @@ void Ide::SetupFormat() {
(edt.tabs_grouping, tabs_grouping)
(edt.tabs_stacking, tabs_stacking)
(edt.tabs_serialize, tabs_serialize)
(edt.spellcheck_comments, spellcheck_comments)
(edt.persistent_find_replace, persistent_find_replace)
(edt.find_replace_restore_pos, find_replace_restore_pos)

View file

@ -90,6 +90,7 @@ void PackageEditor::SaveOptions() {
actual.bold = ~bold;
actual.italic = ~italic;
actual.charset = (byte)(int)~charset;
actual.spellcheck_comments = ~spellcheck_comments;
actual.accepts = Split(accepts.GetText().ToString(), ' ');
actual.noblitz = noblitz;
actual.nowarnings = nowarnings;
@ -116,6 +117,7 @@ void PackageEditor::Empty()
{
FileEmpty();
charset.Disable();
spellcheck_comments.Disable();
noblitz.Disable();
nowarnings.Disable();
description.Disable();
@ -174,6 +176,7 @@ void PackageEditor::PackageCursor()
bold <<= actual.bold;
italic <<= actual.italic;
charset <<= (int)actual.charset;
spellcheck_comments <<= actual.spellcheck_comments;
noblitz = actual.noblitz;
nowarnings = actual.nowarnings;
String s;
@ -187,6 +190,7 @@ void PackageEditor::PackageCursor()
bold.Enable();
italic.Enable();
charset.Enable();
spellcheck_comments.Enable();
noblitz.Enable();
nowarnings.Enable();
accepts.Enable();
@ -579,12 +583,15 @@ PackageEditor::PackageEditor()
CtrlLayoutOKCancel(*this, "Package organizer");
description.Disable();
description <<= THISBACK(Description);
spellcheck_comments.Add(Null, "Default");
DlSpellerLangs(spellcheck_comments);
DlCharsetD(charset);
charset.Disable();
filelist.Disable();
spellcheck_comments.Disable();
accepts.SetFilter(FlagFilter);
accepts <<=
charset <<= THISBACK(SaveOptions);
accepts ^= spellcheck_comments ^= charset ^= THISFN(SaveOptions);
noblitz <<=
nowarnings <<=
pch_file <<=

View file

@ -161,6 +161,7 @@ void WorkspaceWork::SavePackage()
b.data = String::GetVoid();
}
actual.Save(pp);
#if 0 // nobody is using 'init'. to be replaced by "add by include" method
String init;
String mnm = Filter('_' + actualpackage + "_icpp_init_stub", CharFilterMacro);
init << "#ifndef " << mnm << "\r\n";
@ -182,6 +183,7 @@ void WorkspaceWork::SavePackage()
}
init << "#endif\r\n";
SaveChangedFile(SourcePath(actualpackage, "init"), init);
#endif
}
void WorkspaceWork::RestoreBackup()

View file

@ -303,6 +303,8 @@ void DrawFileName(Draw& w, const Rect& r, const String& h, Color ink);
void AddPath(EditString *es);
void InsertPath(EditString *es);
void DlSpellerLangs(DropList& dl);
#include "Assist.h"
void DirSel(EditField& f, FrameRight<Button>& b);
@ -589,6 +591,7 @@ public:
bool find_replace_restore_pos;
bool auto_rescan;
bool auto_check;
int spellcheck_comments;
/*
astyle code formatter control vars
added 2008.01.27 by Massimo Del Fedele
@ -708,8 +711,8 @@ public:
void ChangeFileCharset(const String& name, Package& p, byte charset);
void ChangeCharset();
void FlushFile();
void EditFile0(const String& path, byte charset = CHARSET_DEFAULT, bool astext = false,
const String& header = Null);
void EditFile0(const String& path, byte charset, int spellcheck_comments,
const String& headername = Null);
void EditFile(const String& path);
void AddEditFile(const String& path);
void ReloadFile();

View file

@ -109,20 +109,22 @@ END_LAYOUT
LAYOUT(UppLayout, 936, 576)
UNTYPED(package, LeftPosZ(4, 240).VSizePosZ(4, 196))
UNTYPED(filelist, LeftPosZ(4, 240).BottomPosZ(4, 188))
ITEM(Label, dv___2, SetLabel(t_("Description")).LeftPosZ(248, 64).TopPosZ(4, 19))
ITEM(DataPusher, description, HSizePosZ(308, 208).TopPosZ(4, 20))
ITEM(Label, dv___4, SetLabel(t_("Highlight")).RightPosZ(152, 48).TopPosZ(4, 19))
ITEM(ColorPusher, ink, RightPosZ(100, 52).TopPosZ(4, 20))
ITEM(Label, dv___1, SetLabel(t_("Description")).LeftPosZ(248, 64).TopPosZ(4, 19))
ITEM(DataPusher, description, HSizePosZ(308, 224).TopPosZ(4, 20))
ITEM(Label, dv___3, SetLabel(t_("Highlight")).RightPosZ(144, 68).TopPosZ(4, 19))
ITEM(ColorPusher, ink, RightPosZ(100, 52).TopPosZ(4, 19))
ITEM(Option, bold, SetLabel(t_("Bold")).RightPosZ(52, 44).TopPosZ(4, 20))
ITEM(Option, italic, SetLabel(t_("Italic")).RightPosZ(4, 44).TopPosZ(4, 20))
ITEM(Label, dv___8, SetLabel(t_("&Accepts")).LeftPosZ(368, 44).TopPosZ(28, 19))
ITEM(EditString, accepts, HSizePosZ(412, 356).TopPosZ(28, 19))
ITEM(Label, dv___10, SetLabel(t_("Encoding")).RightPosZ(300, 48).TopPosZ(28, 19))
ITEM(Label, dv___7, SetLabel(t_("&Accepts")).LeftPosZ(248, 44).TopPosZ(28, 19))
ITEM(EditString, accepts, HSizePosZ(308, 548).TopPosZ(28, 19))
ITEM(Label, dv___9, SetLabel(t_("Spellcheck comments")).LeftPosZ(396, 120).TopPosZ(28, 19))
ITEM(DropList, spellcheck_comments, LeftPosZ(512, 68).TopPosZ(28, 19))
ITEM(Label, dv___11, SetLabel(t_("Encoding")).RightPosZ(300, 48).TopPosZ(28, 19))
ITEM(DropList, charset, RightPosZ(184, 112).TopPosZ(28, 19))
ITEM(Option, noblitz, SetLabel(t_("No BLITZ")).RightPosZ(98, 76).TopPosZ(28, 20))
ITEM(Option, nowarnings, SetLabel(t_("No warnings")).RightPosZ(4, 88).TopPosZ(28, 20))
ITEM(ArrayCtrl, option, HSizePosZ(248, 4).VSizePosZ(52, 152))
UNTYPED(filelist, LeftPosZ(4, 240).BottomPosZ(4, 188))
ITEM(ArrayCtrl, fileoption, HSizePosZ(248, 4).BottomPosZ(36, 112))
ITEM(Option, includeable_file, SetLabel(t_("Includeable group")).LeftPosZ(252, 116).BottomPosZ(9, 19))
ITEM(Option, pch_file, SetLabel(t_("Precompile header")).LeftPosZ(368, 120).BottomPosZ(9, 19))
@ -145,7 +147,7 @@ LAYOUT(NewPackageLayout, 728, 560)
UNTYPED(preview, HSizePosZ(248, 8).VSizePosZ(28, 4))
END_LAYOUT
LAYOUT(FileFormatLayout, 348, 160)
LAYOUT(FileFormatLayout, 348, 184)
ITEM(Label, dv___0, SetLabel(t_("&Encoding")).LeftPosZ(8, 64).TopPosZ(8, 20))
ITEM(DropList, charset, LeftPosZ(80, 120).TopPosZ(8, 19))
ITEM(Label, dv___2, SetLabel(t_("&Font")).LeftPosZ(8, 76).TopPosZ(32, 20))
@ -156,8 +158,10 @@ LAYOUT(FileFormatLayout, 348, 160)
ITEM(DropList, highlight, LeftPosZ(80, 260).TopPosZ(80, 19))
ITEM(Label, dv___8, SetLabel(t_("Line endings")).LeftPosZ(8, 96).TopPosZ(104, 19))
ITEM(DropList, line_endings, LeftPosZ(80, 68).TopPosZ(104, 19))
ITEM(Button, ok, SetLabel(t_("OK")).LeftPosZ(208, 64).TopPosZ(128, 22))
ITEM(Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(276, 64).TopPosZ(128, 22))
ITEM(Label, dv___10, SetLabel(t_("Spellcheck comments")).LeftPosZ(8, 120).TopPosZ(128, 19))
ITEM(DropList, spellcheck_comments, LeftPosZ(124, 100).TopPosZ(128, 19))
ITEM(Button, ok, SetLabel(t_("OK")).LeftPosZ(208, 64).TopPosZ(156, 22))
ITEM(Button, cancel, SetLabel(t_("Cancel")).LeftPosZ(276, 64).TopPosZ(156, 22))
END_LAYOUT
LAYOUT(CharsetLayout, 204, 64)
@ -565,6 +569,8 @@ LAYOUT(SetupEditorLayout, 544, 296)
ITEM(Option, tabs_grouping, SetLabel(t_("Group by file folders")).LeftPosZ(304, 132).VCenterPosZ(16, -80))
ITEM(Option, tabs_stacking, SetLabel(t_("Stacking")).LeftPosZ(304, 132).VCenterPosZ(16, -64))
ITEM(Option, tabs_serialize, SetLabel(t_("Persistent tabs")).LeftPosZ(304, 132).VCenterPosZ(16, -48))
ITEM(Label, dv___30, SetLabel(t_("Spellcheck comments")).LeftPosZ(304, 120).TopPosZ(116, 19))
ITEM(DropList, spellcheck_comments, LeftPosZ(428, 92).TopPosZ(116, 19))
END_LAYOUT
LAYOUT(SetupAssistLayout, 532, 212)

View file

@ -71,7 +71,7 @@ void Ide::FileCursor()
if(p != HELPNAME)
p = GetActiveFilePath();
EditFile0(p, f.charset ? f.charset : actual.charset ? actual.charset : default_charset,
false, headername);
Nvl(f.spellcheck_comments, actual.spellcheck_comments, spellcheck_comments));
}
}
@ -136,6 +136,9 @@ void Ide::FileProperties()
d.line_endings.Add(LF, "LF");
d.line_endings <<= findarg(Nvl(editfile_line_endings, line_endings), LF, DETECT_LF) >= 0 ? LF : CRLF;
d.line_endings.Enable(findarg(line_endings, DETECT_CRLF, DETECT_LF) >= 0);
d.spellcheck_comments.Add(Null, "Default");
DlSpellerLangs(d.spellcheck_comments);
d.spellcheck_comments <<= f.spellcheck_comments;
for(;;) {
switch(d.Run()) {
case IDCANCEL:
@ -149,6 +152,7 @@ void Ide::FileProperties()
f.tabsize = Nvl((int)~d.tabsize);
f.font = Nvl((int)~d.font);
f.highlight = ~d.highlight;
f.spellcheck_comments = ~d.spellcheck_comments;
SavePackage();
PackageCursor();
filelist.SetCursor(c);
@ -413,7 +417,8 @@ bool Ide::FileRemove()
return true;
}
void Ide::EditFile0(const String& path, byte charset, bool astext, const String& headername) {
void Ide::EditFile0(const String& path, byte charset, int spellcheck_comments, const String& headername)
{
text_updated.Kill();
AKEditor();
@ -424,12 +429,13 @@ void Ide::EditFile0(const String& path, byte charset, bool astext, const String&
editfile = path;
editor.SetCharset(charset);
editor.SpellcheckComments(spellcheck_comments);
AddLru();
editfile_isfolder = IsFolder(editfile) || IsHelpName(editfile);
svn_dirs = SvnDirs(true).GetCount(); // Perhaps not the best place, but should be ok
bool candesigner = !astext && !(debugger && !editfile_isfolder && (PathIsEqual(path, posfile[0]) || PathIsEqual(path, posfile[0])))
bool candesigner = !(debugger && !editfile_isfolder && (PathIsEqual(path, posfile[0]) || PathIsEqual(path, posfile[0])))
&& editastext.Find(path) < 0 && editashex.Find(path) < 0 && !IsNestReadOnly(editfile);
if(candesigner) {
@ -587,8 +593,9 @@ void Ide::EditAsHex()
editastext.RemoveKey(editfile);
editashex.FindPut(editfile);
byte cs = editor.GetCharset();
int sc = editor.GetSpellcheckComments();
FlushFile();
EditFile0(path, cs);
EditFile0(path, cs, sc);
}
bool Ide::IsDesignerFile(const String& path)
@ -614,8 +621,9 @@ void Ide::EditAsText()
return;
DoEditAsText(path);
byte cs = editor.GetCharset();
int sc = editor.GetSpellcheckComments();
FlushFile();
EditFile0(path, cs);
EditFile0(path, cs, sc);
}
void Ide::EditUsingDesigner()
@ -626,8 +634,9 @@ void Ide::EditUsingDesigner()
editashex.RemoveKey(editfile);
editastext.RemoveKey(editfile);
byte cs = editor.GetCharset();
int sc = editor.GetSpellcheckComments();
FlushFile();
EditFile0(path, cs);
EditFile0(path, cs, sc);
}
void Ide::AddEditFile(const String& path)
@ -785,7 +794,7 @@ void Ide::ReloadFile()
int ln = editor.GetCursorLine();
editfile.Clear();
int sc = filelist.GetSbPos();
EditFile0(fn, editor.GetCharset());
EditFile0(fn, editor.GetCharset(), editor.GetSpellcheckComments());
filelist.SetSbPos(sc);
int l = LocateLine(data, ln, ~editor);
editor.SetCursor(editor.GetPos(l));
@ -875,6 +884,7 @@ void Ide::PassEditor()
editor.SetFocus();
editor.ScrollIntoCursor();
editor2.Annotate(editfile2);
editor2.SpellcheckComments(editor.GetSpellcheckComments());
}
void Ide::ClearEditedFile()

View file

@ -525,6 +525,7 @@ Ide::Ide()
#else
line_endings = DETECT_CRLF;
#endif
spellcheck_comments = LNG_ENGLISH;
/*
astyle code formatter control vars
added 2008.01.27 by Massimo Del Fedele