Jean-Marc Lasgouttes wrote:
Dov Feldstern <dfeldstern-rhxOsnTko2JWk0Htik3J/[EMAIL PROTECTED]> writes:
I've been working on the ignore-spell-check feature using character
attributes (actually inside Font), but I'm having trouble with this. I
think much of the trouble is that I don't understand the intricacies
of Fonts (realized fonts, inheritance/ignore, how fonts are copied,
etc.).
I think you are not too far. See my comment below, which should get
you started if you find the energy to start again :)
Attached find a new patch, based on JMarc's comments (thanks, JMarc!).
Just a recap, this is a character-based approach to the ignore spelling
issue. A new "Misc" options called "Ignore Spelling" has been added to
the Text Style dialog box, which can be toggled on and off. Words marked
as "Ignore Spelling" will (a) be painted with a green underline, and (b)
ignored when spellchecked. Two fixes are still necessary: for (a), add a
preference specifying whether or not to mark Ignore Spelling, and for
(b), I believe that currently only the first letter of the word is used
to determine whether the spelling should be ignored; it seems to me that
it would make more sense to ignore spelling if *any* character in the
word is marked as ignore.
This approach is good, I think, for the "instance-based" ignoring, and
more or less complements Mael's patch, which provides the "type-based"
ignoring. The question is: should we try and merge the two? I (and I
think others) have argued that the "higher-level" functionality ---
i.e., "type-based" ignore --- should be based on the low-level
functionality, in order to simplify the interfaces. I'm not sure how to
achieve that, though. Helge, I think you had some ideas on the subject?
Anyhow, I'm offering this patch for comments, if it's decided in the end
that it's better to just stick with Mael's solution, I won't be crushed.
I still don't love the fact that I'm hijacking Font for this; OTOH, I
still think that insets are not the way to go for this kind of thing...
(Mael --- I still owe you a response about the more "philosphical"
aspects of why I prefer this approach, I'll get to it in a few days, I
hope ;) ).
Good night!
Dov
Index: src/Color.h
===================================================================
--- src/Color.h (revision 19663)
+++ src/Color.h (working copy)
@@ -104,6 +104,8 @@
depthbar,
/// Color for marking foreign language words
language,
+ /// Color for marking text whose spelling is to be ignored
+ ignore_spelling,
/// Text color for command insets
command,
Index: src/Font.cpp
===================================================================
--- src/Font.cpp (revision 19663)
+++ src/Font.cpp (working copy)
@@ -124,6 +124,7 @@
OFF,
OFF,
OFF,
+ OFF,
OFF };
// Initialize static member
@@ -136,7 +137,8 @@
INHERIT,
INHERIT,
INHERIT,
- OFF };
+ OFF,
+ INHERIT };
// Initialize static member
Font::FontBits Font::ignore = {
@@ -148,6 +150,7 @@
IGNORE,
IGNORE,
IGNORE,
+ IGNORE,
IGNORE };
@@ -162,7 +165,8 @@
lhs.emph == rhs.emph &&
lhs.underbar == rhs.underbar &&
lhs.noun == rhs.noun &&
- lhs.number == rhs.number;
+ lhs.number == rhs.number &&
+ lhs.ignore_spelling == rhs.ignore_spelling;
}
@@ -263,6 +267,12 @@
}
+void Font::setIgnoreSpelling(Font::FONT_MISC_STATE s)
+{
+ bits.ignore_spelling = s;
+}
+
+
void Font::setColor(Color_color c)
{
bits.color = int(c);
@@ -410,6 +420,7 @@
setEmph(setMisc(newfont.emph(), emph()));
setUnderbar(setMisc(newfont.underbar(), underbar()));
setNoun(setMisc(newfont.noun(), noun()));
+ setIgnoreSpelling(setMisc(newfont.ignoreSpelling(), ignoreSpelling()));
setNumber(setMisc(newfont.number(), number()));
if (newfont.language() == language() && toggleall)
@@ -444,6 +455,8 @@
setUnderbar(INHERIT);
if (noun() == tmplt.noun())
setNoun(INHERIT);
+ if (ignoreSpelling() == tmplt.ignoreSpelling())
+ setIgnoreSpelling(INHERIT);
if (color() == tmplt.color())
setColor(Color::inherit);
}
@@ -478,6 +491,9 @@
if (bits.noun == INHERIT)
bits.noun = tmplt.bits.noun;
+ if (bits.ignore_spelling == INHERIT)
+ bits.ignore_spelling = tmplt.bits.ignore_spelling;
+
if (bits.color == Color::inherit)
bits.color = tmplt.bits.color;
@@ -491,7 +507,7 @@
return (family() != INHERIT_FAMILY && series() != INHERIT_SERIES &&
shape() != INHERIT_SHAPE && size() != INHERIT_SIZE &&
emph() != INHERIT && underbar() != INHERIT &&
- noun() != INHERIT &&
+ noun() != INHERIT && ignoreSpelling() != INHERIT &&
color() != Color::inherit);
}
@@ -524,8 +540,11 @@
os << bformat(_("Language: %1$s, "),
_(language()->display()));
if (number() != OFF)
- os << bformat(_(" Number %1$s"),
+ os << bformat(_(" Number %1$s, "),
_(GUIMiscNames[number()]));
+ if (ignoreSpelling() != INHERIT)
+ os << bformat(_("Ignore Spelling %1$s"),
+ _(GUIMiscNames[ignoreSpelling()]));
return rtrim(os.str(), ", ");
}
@@ -668,12 +687,16 @@
setEmph(OFF);
} else if (ttok == "no_noun") {
setNoun(OFF);
+ } else if (ttok == "check_spelling") {
+ setIgnoreSpelling(OFF);
} else if (ttok == "emph") {
setEmph(ON);
} else if (ttok == "underbar") {
setUnderbar(ON);
} else if (ttok == "noun") {
setNoun(ON);
+ } else if (ttok == "ignore_spelling") {
+ setIgnoreSpelling(ON);
} else {
lex.printError("Illegal misc type `$$Token'");
}
@@ -726,6 +749,9 @@
if (orgfont.noun() != noun()) {
os << "\\noun " << LyXMiscNames[noun()] << "\n";
}
+ if (orgfont.ignoreSpelling() != ignoreSpelling()) {
+ os << "\\ignore_spelling " << LyXMiscNames[ignoreSpelling()] <<
"\n";
+ }
if (orgfont.color() != color())
os << "\\color " << lcolor.getLyXName(color()) << '\n';
if (orgfont.language() != language() &&
@@ -991,6 +1017,7 @@
<< " emph " << font.bits.emph
<< " underbar " << font.bits.underbar
<< " noun " << font.bits.noun
+ << " ignore_spelling " << font.bits.ignore_spelling
<< " number " << font.bits.number
<< " lang: " << (font.lang ? font.lang->lang() : 0);
}
Index: src/Text.cpp
===================================================================
--- src/Text.cpp (revision 19663)
+++ src/Text.cpp (working copy)
@@ -211,6 +211,9 @@
} else if (token == "\\noun") {
lex.next();
font.setNoun(font.setLyXMisc(lex.getString()));
+ } else if (token == "\\ignore_spelling") {
+ lex.next();
+ font.setIgnoreSpelling(font.setLyXMisc(lex.getString()));
} else if (token == "\\color") {
lex.next();
font.setLyXColor(lex.getString());
Index: src/Font.h
===================================================================
--- src/Font.h (revision 19663)
+++ src/Font.h (working copy)
@@ -183,6 +183,8 @@
FONT_MISC_STATE noun;
///
FONT_MISC_STATE number;
+ ///
+ FONT_MISC_STATE ignore_spelling;
};
///
Font();
@@ -221,6 +223,8 @@
///
FONT_MISC_STATE number() const { return bits.number; }
///
+ FONT_MISC_STATE ignoreSpelling() const { return bits.ignore_spelling; }
+ ///
Color_color color() const;
///
Language const * language() const { return lang; }
@@ -240,6 +244,7 @@
void setUnderbar(Font::FONT_MISC_STATE u);
void setNoun(Font::FONT_MISC_STATE n);
void setNumber(Font::FONT_MISC_STATE n);
+ void setIgnoreSpelling(Font::FONT_MISC_STATE s);
void setColor(Color_color c);
void setLanguage(Language const * l);
Index: src/frontends/controllers/frontend_helpers.cpp
===================================================================
--- src/frontends/controllers/frontend_helpers.cpp (revision 19663)
+++ src/frontends/controllers/frontend_helpers.cpp (working copy)
@@ -208,7 +208,7 @@
vector<BarPair> const getBarData()
{
- vector<BarPair> bar(5);
+ vector<BarPair> bar(6);
BarPair pr;
@@ -232,6 +232,10 @@
pr.second = INHERIT;
bar[4] = pr;
+ pr.first = _("Ignore Spelling");
+ pr.second = IGNORE_SPELLING_TOGGLE;
+ bar[5] = pr;
+
return bar;
}
Index: src/frontends/controllers/ControlSpellchecker.cpp
===================================================================
--- src/frontends/controllers/ControlSpellchecker.cpp (revision 19663)
+++ src/frontends/controllers/ControlSpellchecker.cpp (working copy)
@@ -159,14 +159,15 @@
if (isLetter(cur)) {
if (!inword) {
inword = true;
- ignoreword = false;
cur.resetAnchor();
word.clear();
- lang_code = cur.paragraph().getFontSettings(bp,
cur.pos()).language()->code();
+ Font font = cur.paragraph().getFontSettings(bp,
cur.pos());
+ lang_code = font.language()->code();
+ ignoreword = (font.ignoreSpelling() ==
Font::ON);
}
// Insets like optional hyphens and ligature
// break are part of a word.
- if (!cur.paragraph().isInset(cur.pos())) {
+ if (!cur.paragraph().isInset(cur.pos()) && !ignoreword)
{
Paragraph::value_type const c =
cur.paragraph().getChar(cur.pos());
word += c;
Index: src/frontends/controllers/ControlCharacter.cpp
===================================================================
--- src/frontends/controllers/ControlCharacter.cpp (revision 19663)
+++ src/frontends/controllers/ControlCharacter.cpp (working copy)
@@ -139,9 +139,13 @@
if (font_->noun() == Font::TOGGLE)
return NOUN_TOGGLE;
+ if (font_->ignoreSpelling() == Font::TOGGLE)
+ return IGNORE_SPELLING_TOGGLE;
+
if (font_->emph() == Font::IGNORE &&
font_->underbar() == Font::IGNORE &&
- font_->noun() == Font::IGNORE)
+ font_->noun() == Font::IGNORE &&
+ font_->ignoreSpelling() == Font::IGNORE)
return IGNORE;
return INHERIT;
@@ -168,11 +172,16 @@
case NOUN_TOGGLE:
font_->setNoun(Font::TOGGLE);
break;
+
+ case IGNORE_SPELLING_TOGGLE:
+ font_->setIgnoreSpelling(Font::TOGGLE);
+ break;
case INHERIT:
font_->setEmph(Font::INHERIT);
font_->setUnderbar(Font::INHERIT);
font_->setNoun(Font::INHERIT);
+ font_->setIgnoreSpelling(Font::INHERIT);
break;
}
}
Index: src/frontends/controllers/frontend_helpers.h
===================================================================
--- src/frontends/controllers/frontend_helpers.h (revision 19663)
+++ src/frontends/controllers/frontend_helpers.h (working copy)
@@ -43,6 +43,8 @@
///
NOUN_TOGGLE,
///
+ IGNORE_SPELLING_TOGGLE,
+ ///
INHERIT
};
Index: src/rowpainter.cpp
===================================================================
--- src/rowpainter.cpp (revision 19663)
+++ src/rowpainter.cpp (working copy)
@@ -79,7 +79,9 @@
int maxWidth() { return max_width_; }
private:
+ void paintMarkings(double orig_x, Font const & font, int desc = 0);
void paintForeignMark(double orig_x, Font const & font, int desc = 0);
+ void paintIgnoreSpelling(double orig_x, Font const & font, int desc =
0);
void paintHebrewComposeChar(pos_type & vpos, Font const & font);
void paintArabicComposeChar(pos_type & vpos, Font const & font);
void paintChars(pos_type & vpos, Font const & font,
@@ -394,6 +396,13 @@
}
+void RowPainter::paintMarkings(double orig_x, Font const & font, int desc)
+{
+ paintForeignMark(orig_x, font, desc);
+ paintIgnoreSpelling(orig_x, font, desc);
+}
+
+
void RowPainter::paintForeignMark(double orig_x, Font const & font, int desc)
{
if (!lyxrc.mark_foreign_language)
@@ -408,6 +417,18 @@
}
+void RowPainter::paintIgnoreSpelling(double orig_x, Font const & font, int
desc)
+{
+ //FIXME: if (!lyxrc.mark_ignore_spelling)
+ // return;
+ if (font.ignoreSpelling() == Font::OFF)
+ return;
+
+ int const y = yo_ + 2 + desc;
+ pain_.line(int(orig_x), y, int(x_), y, Color::ignore_spelling);
+}
+
+
void RowPainter::paintFromPos(pos_type & vpos)
{
pos_type const pos = bidi_.vis2log(vpos);
@@ -418,7 +439,7 @@
if (par_.isInset(pos)) {
paintInset(pos, orig_font);
++vpos;
- paintForeignMark(orig_x, orig_font,
+ paintMarkings(orig_x, orig_font,
par_.getInset(pos)->descent());
return;
}
@@ -443,7 +464,7 @@
paintArabicComposeChar(vpos, orig_font);
}
- paintForeignMark(orig_x, orig_font);
+ paintMarkings(orig_x, orig_font);
}
@@ -854,7 +875,7 @@
if (pos >= body_pos)
x_ += separator_;
++vpos;
- paintForeignMark(orig_x, orig_font);
+ paintMarkings(orig_x, orig_font);
} else {
paintFromPos(vpos);
}
Index: src/bufferview_funcs.cpp
===================================================================
--- src/bufferview_funcs.cpp (revision 19663)
+++ src/bufferview_funcs.cpp (working copy)
@@ -64,6 +64,7 @@
<< "emph " << font.emph() << '\n'
<< "underbar " << font.underbar() << '\n'
<< "noun " << font.noun() << '\n'
+ << "ignore_spelling " << font.ignoreSpelling() << '\n'
<< "number " << font.number() << '\n'
<< "color " << font.color() << '\n'
<< "language " << lang << '\n'
@@ -107,7 +108,8 @@
font.setSize(Font::FONT_SIZE(next));
} else if (token == "emph" || token == "underbar" ||
- token == "noun" || token == "number") {
+ token == "noun" || token == "number" ||
+ token == "ignore_spelling") {
int const next = lex.getInteger();
Font::FONT_MISC_STATE const misc =
@@ -121,6 +123,8 @@
font.setNoun(misc);
else if (token == "number")
font.setNumber(misc);
+ else if (token == "ignore_spelling")
+ font.setIgnoreSpelling(misc);
} else if (token == "color") {
int const next = lex.getInteger();
Index: src/Color.cpp
===================================================================
--- src/Color.cpp (revision 19663)
+++ src/Color.cpp (working copy)
@@ -178,6 +178,7 @@
{ shadedbg, N_("shaded box"), "shaded", "#ff0000", "shaded" },
{ depthbar, N_("depth bar"), "depthbar", "IndianRed", "depthbar" },
{ language, N_("language"), "language", "Blue", "language" },
+ { ignore_spelling, N_("ignore spelling"), "ignore_spelling", "Green",
"ignore_spelling" },
{ command, N_("command inset"), "command", "black", "command" },
{ commandbg, N_("command inset background"), "commandbg", "azure",
"commandbg" },
{ commandframe, N_("command inset frame"), "commandframe", "black",
"commandframe" },