Added <prefix> and <suffix> tags;

Added prefix and suffix support to combined_editor;
'always symbol' now checks if the symbols are available in the symbol font;
Fixed parser bug in spec_sort;
A first information field is no longer used as set identification

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@653 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2007-09-01 19:56:43 +00:00
parent 881ea90797
commit bdc1e12e95
13 changed files with 232 additions and 101 deletions
+74 -47
View File
@@ -75,6 +75,7 @@ struct TextElementsFromString {
int soft, kwpph, param, line, soft_line;
int code, code_kw, code_string, param_ref, error;
int param_id;
/// put angle brackets around the text?
bool bracket;
TextElementsFromString()
@@ -86,10 +87,15 @@ struct TextElementsFromString {
void fromString(TextElements& te, const String& text, size_t start, size_t end, const TextStyle& style, Context& ctx) {
te.elements.clear();
end = min(end, text.size());
size_t text_start = start;
// for each character...
for (size_t pos = start ; pos < end ; ) {
Char c = text.GetChar(pos);
if (c == _('<')) {
if (text_start < pos) {
// text element before this tag?
addText(te, text, text_start, pos, style, ctx);
}
size_t tag_start = pos;
pos = skip_tag(text, tag_start);
if (is_substr(text, tag_start, _( "<b"))) bold += 1;
@@ -132,69 +138,90 @@ struct TextElementsFromString {
else if (is_substr(text, tag_start, _("<atom"))) {
// 'atomic' indicator
size_t end_tag = min(end, match_close_tag(text, tag_start));
intrusive_ptr<AtomTextElement> e(new AtomTextElement(text, pos, end_tag));
intrusive_ptr<AtomTextElement> e(new AtomTextElement(pos, end_tag));
fromString(e->elements, text, pos, end_tag, style, ctx);
te.elements.push_back(e);
pos = skip_tag(text, end_tag);
} else if (is_substr(text, tag_start, _( "<error"))) {
// error indicator
size_t end_tag = min(end, match_close_tag(text, tag_start));
intrusive_ptr<ErrorTextElement> e(new ErrorTextElement(text, pos, end_tag));
intrusive_ptr<ErrorTextElement> e(new ErrorTextElement(pos, end_tag));
fromString(e->elements, text, pos, end_tag, style, ctx);
te.elements.push_back(e);
pos = skip_tag(text, end_tag);
} else {
// ignore other tags
}
text_start = pos;
} else {
c = untag_char(c); // unescape
// A character of normal text, add to the last text element (if possible)
SimpleTextElement* e = nullptr;
if (!te.elements.empty()) e = dynamic_cast<SimpleTextElement*>(te.elements.back().get());
if (e && e->end == (bracket ? pos + 1 : pos)) {
e->end = bracket ? pos + 2 : pos + 1; // just move the end, no need to make a new element
e->content += c;
if (bracket) {
// content is "<somethin>g" should be "<something>"
swap(e->content[e->content.size() - 2], e->content[e->content.size() - 1]);
}
} else {
// add a new element for this text
if (symbol > 0 && style.symbol_font.valid()) {
e = new SymbolTextElement(text, pos, pos + 1, style.symbol_font, &ctx);
bracket = false;
} else {
FontP font = style.font.make(
(bold > 0 ? FONT_BOLD : FONT_NORMAL) |
(italic > 0 ? FONT_ITALIC : FONT_NORMAL) |
(soft > 0 ? FONT_SOFT : FONT_NORMAL) |
(kwpph > 0 ? FONT_SOFT : FONT_NORMAL) |
(code > 0 ? FONT_CODE : FONT_NORMAL) |
(code_kw > 0 ? FONT_CODE_KW : FONT_NORMAL) |
(code_string > 0 ? FONT_CODE_STRING : FONT_NORMAL),
param > 0 || param_ref > 0
? &param_colors[(param_id++) % param_colors_count]
: nullptr);
bracket = kwpph > 0 || param > 0;
e = new FontTextElement(
text,
bracket ? pos - 1 : pos,
bracket ? pos + 2 : pos + 1,
font,
soft > 0 ? DRAW_ACTIVE : DRAW_NORMAL,
line > 0 ? BREAK_LINE :
soft_line > 0 ? BREAK_SOFT : BREAK_HARD);
}
if (bracket) {
e->content = String(LEFT_ANGLE_BRACKET) + c + RIGHT_ANGLE_BRACKET;
} else {
e->content = c;
}
te.elements.push_back(TextElementP(e));
}
pos += 1;
}
}
if (text_start < end) {
addText(te, text, text_start, end, style, ctx);
}
}
private:
/// Create a text element for a piece of text
void addText(TextElements& te, const String& text, size_t start, size_t end, const TextStyle& style, Context& ctx) {
String content = untag(text.substr(start, end - start));
assert(content.size() == end-start);
// use symbol font?
if (symbol > 0 && style.symbol_font.valid()) {
te.elements.push_back(new_intrusive5<SymbolTextElement>(content, start, end, style.symbol_font, &ctx));
} else {
// text, possibly mixed with symbols
DrawWhat what = soft > 0 ? DRAW_ACTIVE : DRAW_NORMAL;
LineBreak line_break = line > 0 ? BREAK_LINE :
soft_line > 0 ? BREAK_SOFT : BREAK_HARD;
if (kwpph > 0 || param > 0) {
// bracket the text
content = String(LEFT_ANGLE_BRACKET) + content + RIGHT_ANGLE_BRACKET;
start -= 1;
end += 1;
}
if (style.always_symbol && style.symbol_font.valid()) {
// mixed symbols/text, autodetected by symbol font
size_t text_pos = 0;
size_t pos = 0;
FontP font;
while (pos < end-start) {
if (size_t n = style.symbol_font.font->recognizePrefix(content,pos)) {
// at 'pos' there are n symbol font characters
if (text_pos < pos) {
// text before it?
if (!font) font = makeFont(style);
te.elements.push_back(new_intrusive6<FontTextElement>(content.substr(text_pos, pos-text_pos), start+text_pos, start+pos, font, what, line_break));
}
te.elements.push_back(new_intrusive5<SymbolTextElement>(content.substr(pos,n), start+pos, start+pos+n, style.symbol_font, &ctx));
text_pos = pos += n;
} else {
++pos;
}
}
if (text_pos < pos) {
if (!font) font = makeFont(style);
te.elements.push_back(new_intrusive6<FontTextElement>(content.substr(text_pos), start+text_pos, end, font, what, line_break));
}
} else {
te.elements.push_back(new_intrusive6<FontTextElement>(content, start, end, makeFont(style), what, line_break));
}
}
}
FontP makeFont(const TextStyle& style) {
return style.font.make(
(bold > 0 ? FONT_BOLD : FONT_NORMAL) |
(italic > 0 ? FONT_ITALIC : FONT_NORMAL) |
(soft > 0 ? FONT_SOFT : FONT_NORMAL) |
(kwpph > 0 ? FONT_SOFT : FONT_NORMAL) |
(code > 0 ? FONT_CODE : FONT_NORMAL) |
(code_kw > 0 ? FONT_CODE_KW : FONT_NORMAL) |
(code_string > 0 ? FONT_CODE_STRING : FONT_NORMAL),
param > 0 || param_ref > 0
? &param_colors[(param_id++) % param_colors_count]
: nullptr);
}
};
+10 -25
View File
@@ -57,12 +57,10 @@ struct CharInfo {
/// A section of text that can be rendered using a TextViewer
class TextElement : public IntrusivePtrBase<TextElement> {
public:
/// The text of which a subsection is drawn
String text;
/// What section of the input string is this element?
size_t start, end;
inline TextElement(const String& text, size_t start ,size_t end) : text(text), start(start), end(end) {}
inline TextElement(size_t start ,size_t end) : start(start), end(end) {}
virtual ~TextElement() {}
/// Draw a subsection section of the text in the given rectangle
@@ -109,8 +107,8 @@ class TextElements {
/// A text element that just shows text
class SimpleTextElement : public TextElement {
public:
SimpleTextElement(const String& text, size_t start, size_t end)
: TextElement(text, start, end), content(text.substr(start,end-start))
SimpleTextElement(const String& content, size_t start, size_t end)
: TextElement(start, end), content(content)
{}
String content; ///< Text to show
};
@@ -118,8 +116,8 @@ class SimpleTextElement : public TextElement {
/// A text element that uses a normal font
class FontTextElement : public SimpleTextElement {
public:
FontTextElement(const String& text, size_t start, size_t end, const FontP& font, DrawWhat draw_as, LineBreak break_style)
: SimpleTextElement(text, start, end)
FontTextElement(const String& content, size_t start, size_t end, const FontP& font, DrawWhat draw_as, LineBreak break_style)
: SimpleTextElement(content, start, end)
, font(font), draw_as(draw_as), break_style(break_style)
{}
@@ -136,8 +134,8 @@ class FontTextElement : public SimpleTextElement {
/// A text element that uses a symbol font
class SymbolTextElement : public SimpleTextElement {
public:
SymbolTextElement(const String& text, size_t start, size_t end, const SymbolFontRef& font, Context* ctx)
: SimpleTextElement(text, start, end)
SymbolTextElement(const String& content, size_t start, size_t end, const SymbolFontRef& font, Context* ctx)
: SimpleTextElement(content, start, end)
, font(font), ctx(*ctx)
{}
@@ -155,7 +153,7 @@ class SymbolTextElement : public SimpleTextElement {
/// A TextElement consisting of sub elements
class CompoundTextElement : public TextElement {
public:
CompoundTextElement(const String& text, size_t start, size_t end) : TextElement(text, start, end) {}
CompoundTextElement(size_t start, size_t end) : TextElement(start, end) {}
virtual void draw (RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
virtual void getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const;
@@ -168,7 +166,7 @@ class CompoundTextElement : public TextElement {
/// A TextElement drawn using a grey background
class AtomTextElement : public CompoundTextElement {
public:
AtomTextElement(const String& text, size_t start, size_t end) : CompoundTextElement(text, start, end) {}
AtomTextElement(size_t start, size_t end) : CompoundTextElement(start, end) {}
virtual void draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
};
@@ -176,23 +174,10 @@ class AtomTextElement : public CompoundTextElement {
/// A TextElement drawn using a red wavy underline
class ErrorTextElement : public CompoundTextElement {
public:
ErrorTextElement(const String& text, size_t start, size_t end) : CompoundTextElement(text, start, end) {}
ErrorTextElement(size_t start, size_t end) : CompoundTextElement(start, end) {}
virtual void draw(RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
};
// ----------------------------------------------------------------------------- : Other text elements
/*
/// A text element that displays a horizontal separator line
class HorizontalLineTextElement : public TextElement {
public:
HorizontalLineTextElement(const String& text, size_t start ,size_t end) : TextElement(text, start, end) {}
virtual void draw (RotatedDC& dc, double scale, const RealRect& rect, const double* xs, DrawWhat what, size_t start, size_t end) const;
virtual void getCharInfo(RotatedDC& dc, double scale, vector<CharInfo>& out) const;
virtual double minScale() const;
};
*/
// ----------------------------------------------------------------------------- : EOF
#endif
+1 -6
View File
@@ -328,12 +328,7 @@ void TextViewer::setExactScrollPosition(double pos) {
// ----------------------------------------------------------------------------- : Elements
void TextViewer::prepareElements(const String& text, const TextStyle& style, Context& ctx) {
if (style.always_symbol) {
elements.elements.clear();
elements.elements.push_back(new_intrusive5<SymbolTextElement>(text, 0, text.size(), style.symbol_font, &ctx));
} else {
elements.fromString(text, 0, text.size(), style, ctx);
}
elements.fromString(text, 0, text.size(), style, ctx);
}