Example #1
0
void RichTxt::CombineFormat(FormatInfo& fi, int pi, int pi2, bool& first, const RichStyles& style) const
{
	while(pi < pi2) {
		if(IsTable(pi)) {
			const RichTable& tab = part[pi].Get<RichTable>();
			for(int i = 0; i < tab.GetRows(); i++)
				for(int j = 0; j < tab.GetColumns(); j++)
					if(tab(i, j)) {
						const RichTxt& txt = tab[i][j].text;
						txt.CombineFormat(fi, 0, txt.GetPartCount(), first, style);
					}
		}
		else {
			RichPara pa = Get(pi, style);
			if(first) {
				fi.Set(pa.format);
				if(pa.GetCount())
					fi.Set(pa[0].format);
				first = false;
			}
			else
				fi.Combine(pa.format);
			for(int i = first; i < pa.GetCount(); i++)
				fi.Combine(pa[i].format);
		}
		pi++;
	}
}
Example #2
0
void RichTxt::SaveFormat(Formating& r, int p1, int p2, const RichStyles& style) const
{
	Array<RichObject> dummy;
	for(int i = p1; i <= p2; i++)
		if(IsTable(i)) {
			const RichTable& tab = part[i].Get<RichTable>();
			for(int i = 0; i < tab.GetRows(); i++)
				for(int j = 0; j < tab.GetColumns(); j++)
					if(tab(i, j)) {
						const RichTxt& txt = tab[i][j].text;
						txt.SaveFormat(r, 0, txt.GetPartCount() - 1, style);
					}
		}
		else {
			RichPara pa = Get(i, style);
			for(int i = 0; i < pa.GetCount(); i++) {
				RichPara::Part& p = pa[i];
				int q = p.GetLength();
				p.field = Id();
				p.object = RichObject();
				WString h;
				while(q) {
					int c = min(q, 50000);
					h.Cat(c + 32);
					q -= c;
				}
				p.text = h;
			}
			r.styleid.Add(pa.format.styleid);
			r.format.Add(pa.Pack(GetStyle(style, pa.format.styleid).format, dummy));
		}
}
Example #3
0
void RichTxt::RestoreFormat(int pi, const Formating& info, int& ii, const RichStyles& style)
{
	Array<RichObject> dummy;
	while(ii < info.format.GetCount() && pi < GetPartCount()) {
		if(IsTable(pi)) {
			RichTable& tab = part[pi].Get<RichTable>();
			for(int i = 0; i < tab.GetRows(); i++)
				for(int j = 0; j < tab.GetColumns(); j++) {
					if(tab(i, j)) {
						if(ii >= info.format.GetCount())
							return;
						tab.InvalidateRefresh(i, j);
						tab[i][j].text.RestoreFormat(0, info, ii, style);
					}
				}
			pi++;
		}
		else {
			RichPara pa = Get(pi, style);
			RichPara pf;
			pf.Unpack(info.format[ii], dummy, GetStyle(style, info.styleid[ii]).format);
			RichPara t;
			t.format = pf.format;
			int si = 0;
			int sp = 0;
			for(int j = 0; j < pf.GetCount(); j++) {
				const RichPara::Part& q = pf[j];
				for(int k = 0; k < q.text.GetLength(); k++) {
					int len = q.text[k] - 32;
					t.part.Add().format = q.format;
					while(len) {
						const RichPara::Part& p = pa[si];
						if(p.IsText()) {
							int l = min(len, p.GetLength() - sp);
							t.part.Top().text.Cat(p.text.Mid(sp, l));
							sp += l;
							len -= l;
							ASSERT(sp <= p.GetLength());
							if(sp >= p.GetLength()) {
								sp = 0;
								si++;
							}
						}
						else {
							ASSERT(sp == 0);
							(t.part.Add() = pa[si++]).format = q.format;
							len--;
							sp = 0;
						}
					}
				}
			}
			ASSERT(si == pa.GetCount() && sp == 0);
			Put(pi, t, style);
			ii++;
			pi++;
		}
	}
}
Example #4
0
void RichTxt::Paint(PageDraw& pw, RichContext rc, const PaintInfo& _pi) const
{
	PaintInfo pi = _pi;
	int parti = 0;
	int pos = 0;
	RichPara::Number n;
	while(rc.py < pi.bottom && parti < part.GetCount()) {
		if(part[parti].Is<RichTable>()) {
			pi.tablesel--;
			const RichTable& tab = GetTable(parti);
			tab.Paint(pw, rc, pi);
			rc.py = tab.GetHeight(rc);
			pi.tablesel -= tab.GetTableCount();
		}
		else {
			const Para& pp = part[parti].Get<Para>();
			if(pp.number) {
				n.TestReset(*pp.number);
				n.Next(*pp.number);
			}
			PageY next = GetNextPageY(parti, rc);
			if(next >= pi.top) {
				int nbefore = 0;
				int nline = 0;
				if(pp.keepnext && parti + 1 < part.GetCount() && part[parti + 1].Is<Para>()) {
					Sync(parti + 1, rc);
					const Para& pp = part[parti + 1].Get<Para>();
					nbefore = pp.before;
					nline = pp.linecy[0];
				}
				RichPara p = Get(parti, rc.styles);
				if(pi.spellingchecker) {
					if(!pp.checked) {
						pp.spellerrors = (*pi.spellingchecker)(p);
						pp.checked = true;
					}
				}
				else {
					pp.checked = false;
					pp.spellerrors.Clear();
				}
				if(IsPainting(pw, pi.zoom, rc.page, rc.py, next))
					p.Paint(pw, rc.page, rc.py, pi, n, pp.spellerrors, nbefore, nline);
			}
			rc.py = next;
		}
		int l = GetPartLength(parti) + 1;
		pi.highlightpara -= l;
		pi.sell -= l;
		pi.selh -= l;
		pos += l;
		++parti;
	}
}
Example #5
0
void RichTxt::ApplyZoom(Zoom z, const RichStyles& ostyle, const RichStyles& zstyle)
{
	for(int i = 0; i < GetPartCount(); i++)
		if(IsTable(i))
			part[i].Get<RichTable>().ApplyZoom(z, ostyle, zstyle);
		else {
			RichPara p = Get(i, ostyle);
			p.ApplyZoom(z);
			Set(i, p, zstyle);
		}
}
Example #6
0
void RichEdit::RightDown(Point p, dword flags)
{
	useraction = true;
	NextUndo();
	MenuBar menu;
	int l, h;
	Rect ocr = GetCaretRect();
	int fieldpos = -1;
	Id field;
	String ofieldparam;
	RichObject o;
	bar_object.Clear();
	bar_fieldparam = Null;
	if(!GetSelection(l, h)) {
		LeftDown(p, flags);
		if(objectpos >= 0)
			o = bar_object = GetObject();
		else {
			RichPos p = cursorp;
			field = p.field;
			bar_fieldparam = p.fieldparam;
			RichPara::FieldType *ft = RichPara::fieldtype().Get(field, NULL);
			if(ft) {
				ofieldparam = bar_fieldparam;
				fieldpos = cursor;
			}
		}
	}
	WhenBar(menu);
	Rect r = GetCaretRect();
	Refresh(r);
	Refresh(ocr);
	paintcarect = true;
	menu.Execute();
	paintcarect = false;
	Refresh(r);
	if(bar_object && o && o.GetSerialId() != bar_object.GetSerialId())
		ReplaceObject(bar_object);
	if(fieldpos >= 0 && bar_fieldparam != ofieldparam) {
		RichText::FormatInfo f = text.GetFormatInfo(fieldpos, 1);
		Remove(fieldpos, 1);
		RichPara p;
		p.Cat(field, bar_fieldparam, f);
		RichText clip;
		clip.Cat(p);
		Insert(fieldpos, clip, false);
		Finish();
	}
	bar_object.Clear();
	bar_fieldparam = Null;
}
Example #7
0
void RichTxt::Apply(const RichText::FormatInfo& fi, RichPara& pa, const RichStyles& style)
{
	ApplyStyle(fi, pa, style);
	for(int i = 0; i < pa.GetCount(); i++)
		fi.ApplyTo(pa[i].format);
	fi.ApplyTo(pa.format);
}
Example #8
0
void RichQtfParser::EndPart()
{
	if(istable) {
		if(paragraph.GetCount() == 0 && text.GetCount() == 0)
			if(table.GetCount())
				table.Top().text.CatPick(pick(tablepart));
			else
				target.CatPick(pick(tablepart));
		else {
			paragraph.part.Clear();
			text.Clear();
		}
	}
	else {
		Flush();
		bool b = paragraph.format.newpage;
		if(breakpage)
			paragraph.format.newpage = true;
		if(table.GetCount())
			table.Top().text.Cat(paragraph, target.GetStyles());
		else
			target.Cat(paragraph);
		paragraph.part.Clear();;
		paragraph.format.newpage = b;
		SetFormat();
		breakpage = false;
	}
	istable = false;
}
Example #9
0
void RichQtfParser::Flush() {
	if(text.GetLength()) {
		ASSERT(!istable);
		paragraph.Cat(text, format);
		text.Clear();
	}
}
Example #10
0
NAMESPACE_UPP

int RichTxt::GetWidth(const RichStyles& st) const
{
	int cx = 0;
	for(int i = 0; i < part.GetCount(); i++) {
		if(IsPara(i)) {
			RichPara p = Get(i, st);
			RichPara::Lines pl = p.FormatLines(INT_MAX);
			int ccx = 0;
			Sum(ccx, ~pl.width, ~pl.width + pl.clen);
			cx = max(cx, ccx);
		}
		else
			return 10000;
	}
	return cx;
}
Example #11
0
void RichTxt::Sync0(const Para& pp, int parti, const RichContext& rc) const
{
	int cx = rc.page.Width();
	pp.cx = cx;
	RichPara p = Get(parti, rc.styles);
	RichPara::Lines pl = p.FormatLines(cx);
	pp.ruler = p.format.ruler;
	pp.before = p.format.before;
	pp.linecy.Clear();
	pp.linecy.SetCount(pl.GetCount());
	for(int i = 0; i < pl.GetCount(); i++)
		pp.linecy[i] = pl[i].Sum();
	pp.cy = Sum0(pp.linecy);
	pp.after = p.format.after;
	pp.newpage = p.format.newpage;
	pp.keep = p.format.keep;
	pp.keepnext = p.format.keepnext;
	pp.orphan = p.format.orphan;
}
Example #12
0
void RichTxt::ApplyStyle(const RichText::FormatInfo& fi, RichPara& pa, const RichStyles& style)
{
	if(fi.paravalid & STYLE) {
		int q = style.Find(fi.styleid);
		if(q >= 0) {
			pa.ApplyStyle(style[q].format);
			pa.format.styleid = fi.styleid;
		}
	}
}
Example #13
0
NAMESPACE_UPP

void RichTxt::GetAllLanguages(Index<int>& all) const
{
	for(int i = 0; i < part.GetCount(); i++) {
		if(IsTable(i)) {
			const RichTable& tab = part[i].Get<RichTable>();
			for(int i = 0; i < tab.GetRows(); i++)
				for(int j = 0; j < tab.GetColumns(); j++)
					if(tab(i, j))
						tab[i][j].text.GetAllLanguages(all);
		}
		else {
			RichPara p = Get(i, RichStyle::GetDefault());
			all.FindAdd(p.format.language);
			for(int i = 0; i < p.GetCount(); i++)
				all.FindAdd(p[i].format.language);
		}
	}
}
Example #14
0
void DashEdit::SetData(const Value& data)
{
	RichText text;
	String d = data;
	RichPara para;
	RichPara::Format f;
	for(const char *s = d; *s; s++)
		if(*s == '\n') {
			text.Cat(para);
			para.part.Clear();
		}
		else
		if(*s == '~')
			f.dashed = !f.dashed;
		else
		if((byte)*s >= ' ')
			para.Cat(String(*s, 1).ToWString(), f);
	text.Cat(para);
	Pick(text);
}
Example #15
0
Value DashEdit::GetData() const
{
	const RichText& txt = Get();
	String r;
	for(int i = 0; i < txt.GetPartCount(); i++) {
		if(i)
			r << "\r\n";
		if(txt.IsPara(i)) {
			RichPara p = txt.Get(i);
			for(int j = 0; j < p.GetCount(); j++)
				if(p.part[j].format.dashed) {
					r << '~';
					r << p.part[j].text;
					r << '~';
				}
				else
					r << p.part[j].text;
		}
	}
	return r;
}
Example #16
0
Bits RichEdit::SpellParagraph(const RichPara& para)
{
	int len = para.GetLength();
	Buffer<wchar> text(len);
	Buffer<int> lang(len);
	wchar *s = text;
	int *g = lang;
	for(int i = 0; i < para.GetCount(); i++) {
		const RichPara::Part& p = para[i];
		if(p.IsText()) {
			int l = p.text.GetLength();
			memcpy(s, p.text, l * sizeof(wchar));
			Fill(g, g + l, fixedlang ? fixedlang : p.format.language);
			s += l;
			g += l;
		}
		else {
			*s++ = 127;
			*g++ = 0;
		}
	}
	Bits e;
	s = text;
	wchar *end = text + len;
	while(s < end) {
		if(IsLetter(*s)) {
			const wchar *q = s;
			while(s < end && IsLetter(*s) || s + 1 < end && *s == '\'' && IsLetter(s[1]))
				s++;
			if(!SpellWord(q, int(s - q), lang[q - text]))
				e.Set(int(q - text), true, int(s - q));
		}
		else
			s++;
	}
	return e;
}
Example #17
0
void RichQtfParser::Error(const char *s) {
	RichPara::CharFormat ef;
	(Font&) ef = Arial(84).Bold().Underline();
	ef.ink = Red;
	WString e;
	e << "ERROR: " << s;
	if(*term)
		e << ": " << Filter(String(term, min<int>((int)strlen(term), 20)), NoLow).ToWString();
	else
		e << ".";
	paragraph.Cat(e, ef);
	target.Cat(paragraph);
	FlushStyles();
	throw Exc();
}
Example #18
0
void RichEdit::LeftDouble(Point p, dword flags)
{
	NextUndo();
	int c = GetMousePos(p);
	if(c >= 0) {
		if(objectpos == c) {
			RichObject object = GetObject();
			if(!object) return;
			RichObject o = object;
			o.DefaultAction(context);
			if(object.GetSerialId() != o.GetSerialId())
				ReplaceObject(o);
		}
		else {
			RichPos rp = cursorp;
			RichPara::FieldType *ft = RichPara::fieldtype().Get(rp.field, NULL);
			if(ft) {
				int fieldpos = cursor;
				ft->DefaultAction(&rp.fieldparam);
				RichText::FormatInfo f = text.GetFormatInfo(fieldpos, 1);
				Remove(fieldpos, 1);
				RichPara p;
				p.Cat(rp.field, rp.fieldparam, f);
				RichText clip;
				clip.Cat(p);
				Insert(fieldpos, clip, false);
				Finish();
			}
			else {
				int l, h;
				if(GetWordSelection(c, l, h))
					SetSelection(l, h);
			}
		}
	}
}
Example #19
0
	virtual bool operator()(int pos, const RichPara& para)
	{
		WString ptext = para.GetText();
		if(pos + ptext.GetLength() > cursor && ptext.GetLength() >= len) {
			const wchar *q = ptext;
			const wchar *e = ptext.End() - len;
			if(cursor >= pos)
				q += cursor - pos;
			while(q <= e) {
				if(compare3(q, upperw, lowerw, len) &&
				   (!ww || (q + len == e || !IsLetter(q[len])) &&
				           (q == ptext || !IsLetter(q[-1])))) {
					fpos = int(q - ~ptext + pos);
					return true;
				}
				q++;
			}
		}
		return false;
	}
Example #20
0
	virtual bool operator()(int pos, const RichPara& para)
	{
		for(int i = 0; i < para.GetCount(); i++) {
			String l = para[i].format.link;
			if(!IsNull(l)) {
				if(l[0] == ':') {
					int q = reflink->Find(l);
					int w = q;
					if(q < 0)
						q = reflink->Find(l + "::class");
					if(q < 0)
						q = reflink->Find(l + "::struct");
					if(q < 0)
						q = reflink->Find(l + "::union");
					if(q >= 0)
						l = (*reflink)[q];
				}
				link.FindAdd(Nvl(reflink->Get(l, Null), l));
			}
		}
		return false;
	}
Example #21
0
void RichQtfParser::Parse(const char *qtf, int _accesskey)
{
	accesskey = _accesskey;
	term = qtf;
	while(*term) {
		if(Key('[')) {
			Flush();
			fstack.Add(format);
			for(;;) {
				int c = *term;
				if(!c)
					Error("Unexpected end of text");
				term++;
				if(c == ' ' || c == '\n') break;
				switch(c) {
				case 's': {
					Uuid id;
					c = *term;
					if(Key('\"') || Key('\''))
						id = target.GetStyleId(GetText(c));
					else {
						int i = ReadNumber();
						if(i >= 0 && i < styleid.GetCount())
							id = styleid[i];
						else
							id = RichStyle::GetDefaultId();
					}
					const RichStyle& s = target.GetStyle(id);
					bool p = format.newpage;
					int lng = format.language;
					(RichPara::Format&) format = s.format;
					format.styleid = id;
					format.language = lng;
					format.newpage = p;
					break;
				}
				case '/': format.Italic(!format.IsItalic()); break;
				case '*': format.Bold(!format.IsBold()); break;
				case '_': format.Underline(!format.IsUnderline()); break;
				case 'T': format.NonAntiAliased(!format.IsNonAntiAliased()); break;
				case '-': format.Strikeout(!format.IsStrikeout()); break;
				case 'c': format.capitals = !format.capitals; break;
				case 'd': format.dashed = !format.dashed; break;
				case '`': format.sscript = format.sscript == 1 ? 0 : 1; break;
				case ',': format.sscript = format.sscript == 2 ? 0 : 2; break;
				case '^': format.link = GetText('^'); break;
				case 'I': format.indexentry = FromUtf8(GetText(';')); break;
				case '+': format.Height(GetNumber()); break;
				case '@': format.ink = GetColor(); break;
				case '$': format.paper = GetColor(); break;
				case 'A': format.Face(Font::ARIAL); break;
				case 'R': format.Face(Font::ROMAN); break;
				case 'C': format.Face(Font::COURIER); break;
				case 'G': format.Face(Font::STDFONT); break;
				case 'S':
#ifdef PLATFORM_WIN32
					format.Face(Font::SYMBOL);
#endif
					break;
				case '.': {
					int n = GetNumber();
					if(n >= Font::GetFaceCount())
						Error("Invalid face number");
					format.Face(n); break;
				}
				case '!': {
						String fn = GetText('!');
						int i = Font::FindFaceNameIndex(fn);
						if(i < 0)
							i = Font::ARIAL;
						format.Face(i);
					}
					break;
				case '{': {
						String cs = GetText('}');
						if(cs.GetLength() == 1) {
							int c = *cs;
							if(c == '_')
								format.charset = CHARSET_UTF8;
							if(c >= '0' && c <= '8')
								format.charset = c - '0' + CHARSET_WIN1250;
							if(c >= 'A' && c <= 'Z')
								format.charset = c - '0' + CHARSET_ISO8859_1;
						}
						else {
							for(int i = 0; i < CharsetCount(); i++)
								if(stricmp(CharsetName(i), cs) == 0) {
									format.charset = i;
									break;
								}
						}
						break;
					}
				case '%': {
						String h;
						if(*term == '-') {
							format.language = 0;
							term++;
						}
						else
						if(*term == '%') {
							format.language = LNG_ENGLISH;
							term++;
						}
						else {
							while(*term && h.GetLength() < 5)
								h.Cat(*term++);
							format.language = LNGFromText(h);
						}
						break;
					}
				case 'g':
					format.Face(Font::STDFONT);
					format.Height(GetRichTextScreenStdFontHeight());
					break;
				default:
					if(c >= '0' && c <= '9') {
						format.Height(QTFFontHeight[c - '0']);
						break;
					}
					switch(c) {
					case ':': format.label = GetText(':'); break;
					case '<': format.align = ALIGN_LEFT; break;
					case '>': format.align = ALIGN_RIGHT; break;
					case '=': format.align = ALIGN_CENTER; break;
					case '#': format.align = ALIGN_JUSTIFY; break;
					case 'l': format.lm = GetNumber(); break;
					case 'r': format.rm = GetNumber(); break;
					case 'i': format.indent = GetNumber(); break;
					case 'b': format.before = GetNumber(); break;
					case 'a': format.after = GetNumber(); break;
					case 'P': format.newpage = !format.newpage; break;
					case 'k': format.keep = !format.keep; break;
					case 'K': format.keepnext = !format.keepnext; break;
					case 'H': format.ruler = GetNumber(); break;
					case 'h': format.rulerink = GetColor(); break;
					case 'L': format.rulerstyle = GetNumber(); break;
					case 'Q': format.orphan = !format.orphan; break;
					case 'n': format.before_number = GetText(';'); break;
					case 'm': format.after_number = GetText(';'); break;
					case 'N': {
						memset(format.number, 0, sizeof(format.number));
						format.reset_number = false;
						int i = 0;
						while(i < 8) {
							int c;
							if(Key('-'))
								c = RichPara::NUMBER_NONE;
							else
							if(Key('1'))
								c = RichPara::NUMBER_1;
							else
							if(Key('0'))
								c = RichPara::NUMBER_0;
							else
							if(Key('a'))
								c = RichPara::NUMBER_a;
							else
							if(Key('A'))
								c = RichPara::NUMBER_A;
							else
							if(Key('i'))
								c = RichPara::NUMBER_i;
							else
							if(Key('I'))
								c = RichPara::NUMBER_I;
							else
								break;
							format.number[i++] = c;
						}
						if(Key('!'))
							format.reset_number = true;
						break;
					}
					case 'o': format.bullet = RichPara::BULLET_ROUND;
					          format.indent = 150; break;
					case 'O':
						if(Key('_'))
							format.bullet = RichPara::BULLET_NONE;
						else {
							int c = *term++;
							if(!c)
								Error("Unexpected end of text");
							format.bullet =
							                c == '1' ? RichPara::BULLET_ROUNDWHITE :
							                c == '2' ? RichPara::BULLET_BOX :
							                c == '3' ? RichPara::BULLET_BOXWHITE :
							                c == '9' ? RichPara::BULLET_TEXT :
							                           RichPara::BULLET_ROUND;
						}
						break;
					case 'p':
						switch(*term++) {
						case 0:   Error("Unexpected end of text");
						case 'h': format.linespacing = RichPara::LSP15; break;
						case 'd': format.linespacing = RichPara::LSP20; break;
						default:  format.linespacing = RichPara::LSP10;
						}
						break;
					case 't':
						if(IsDigit(*term)) //temporary fix... :(
							format.tabsize = ReadNumber();
						break;
					case '~': {
							if(Key('~'))
								format.tab.Clear();
							else {
								RichPara::Tab tab;
								Key('<');
								if(Key('>'))
									tab.align = ALIGN_RIGHT;
								if(Key('='))
									tab.align = ALIGN_CENTER;
								if(Key('.'))
									tab.fillchar = 1;
								if(Key('-'))
									tab.fillchar = 2;
								if(Key('_'))
									tab.fillchar = 3;
								int rightpos = Key('>') ? RichPara::TAB_RIGHTPOS : 0;
								tab.pos = rightpos | ReadNumber();
								format.tab.Add(tab);
							}
						}
						break;
					default:
						continue;
					}
				}
			}
			SetFormat();
		}
		else
		if(Key(']')) {
			Flush();
			if(fstack.GetCount()) {
				format = fstack.Top();
				fstack.Drop();
			}
			else
				Error("Unmatched ']'");
		}
		else
		if(Key2('{')) {
			if(oldtab)
				Error("{{ in ++ table");
			if(text.GetLength() || paragraph.GetCount())
				EndPart();
			table.Add();
			int r = IsDigit(*term) ? ReadNumber() : 1;
			Table().AddColumn(r);
			while(Key(':'))
				Table().AddColumn(ReadNumber());
			TableFormat();
			SetFormat();
		}
		else
		if(Key2('}')) {
			if(oldtab)
				Error("}} in ++ table");
			FinishTable();
		}
		else
		if(Key2('+'))
			if(oldtab)
				FinishOldTable();
			else {
				Flush();
				if(text.GetLength() || paragraph.GetCount())
					EndPart();
				Tab& b = table.Add();
				b.rown.Add(0);
				b.hspan = 1;
				b.Old();
				oldtab = true;
			}
		else
		if(Key2('|'))
			FinishCell();
		else
		if(Key2('-')) {
			FinishCell();
			table.Top().rown.Add(0);
		}
		else
		if(Key2(':')) {
			if(!oldtab)
				FinishCell();
			TableFormat(oldtab);
		}
		else
		if(Key2('^')) {
			EndPart();
			breakpage = true;
		}
		else
		if(Key2('@')) {
			ReadObject();
		}
		else
		if(Key2('@', '$')) {
			String xu;
			while(isxdigit(*term))
				xu.Cat(*term++);
			int c = stou(~xu, NULL, 16);
			if(c >= 32)
				Cat(c);
			if(*term == ';')
				term++;
			SetFormat();
		}
		else
		if(Key2('^', 'H'))
			target.SetHeaderQtf(GetText2('^', '^'));
		else
		if(Key2('^', 'F'))
			target.SetFooterQtf(GetText2('^', '^'));
		else
		if(Key2('{', ':')) {
			Flush();
			String field = GetText(':');
			String param = GetText(':');
			Id fid(field);
			if(RichPara::fieldtype().Find(fid) >= 0)
				paragraph.Cat(fid, param, format);
			Key('}');
		}
		else
		if(Key('&')) {
			SetFormat();
			EndPart();
		}
		else
		if(Key2('$')) {
			Flush();
			int i = GetNumber();
			Uuid id;
			RichStyle style;
			style.format = format;
			if(Key(','))
				stylenext.At(i, 0) = GetNumber();
			else
				stylenext.At(i, 0) = i;
			if(Key('#')) {
				String xu;
				while(isxdigit(*term))
					xu.Cat(*term++);
				if(xu.GetLength() != 32)
					Error("Invalid UUID !");
				id = ScanUuid(xu);
			}
			else
				if(i)
					id = Uuid::Create();
				else
					id = RichStyle::GetDefaultId();
			if(Key(':'))
				style.name = GetText(']');
			if(fstack.GetCount()) {
				format = fstack.Top();
				fstack.Drop();
			}
			target.SetStyle(id, style);
			styleid.At(i, RichStyle::GetDefaultId()) = id;
			if(id == RichStyle::GetDefaultId()) {
				bool p = format.newpage;
				int lng = format.language;
				(RichPara::Format&) format = style.format;
				format.styleid = id;
				format.language = lng;
				format.newpage = p;
			}
		}
		else
		if(*term == '_') {
			SetFormat();
			text.Cat(160);
			term++;
		}
		else
		if(Key2('-', '|')) {
			SetFormat();
			text.Cat(9);
		}
		else
		if(*term == '\1') {
			if(istable)
				EndPart();
			SetFormat();
			const char *b = ++term;
			for(; *term && *term != '\1'; term++) {
				if((byte)*term == '\n') {
					text.Cat(ToUnicode(b, (int)(term - b), format.charset));
					EndPart();
					b = term + 1;
				}
				if((byte)*term == '\t') {
					text.Cat(ToUnicode(b, (int)(term - b), format.charset));
					text.Cat(9);
					b = term + 1;
				}
			}
			text.Cat(ToUnicode(b, (int)(term - b), format.charset));
			if(*term == '\1')
				term++;
		}
		else {
			if(!Key('`')) Key('\\');
			if((byte)*term >= ' ') {
				SetFormat();
				do {
					if(istable)
						EndPart();
					if(format.charset == CHARSET_UTF8) {
						word code = (byte)*term++;
						if(code <= 0x7F)
							Cat(code);
						else
						if(code <= 0xDF) {
							if(*term == '\0') break;
							int c0 = (byte)*term++;
							if(c0 < 0x80)
								Error("Invalid UTF-8 sequence");
							Cat(((code - 0xC0) << 6) + c0 - 0x80);
						}
						else
						if(code <= 0xEF) {
							int c0 = (byte)*term++;
							int c1 = (byte)*term++;
							if(c0 < 0x80 || c1 < 0x80)
								Error("Invalid UTF-8 sequence");
							Cat(((code - 0xE0) << 12) + ((c0 - 0x80) << 6) + c1 - 0x80);
						}
						else
							Error("Invalid UTF-8 sequence");
					}
					else
						Cat(ToUnicode((byte)*term++, format.charset));
				}
				while((byte)*term >= 128 || s_nodeqtf[(byte)*term]);
			}
			else
			if(*term)
				term++;
		}
	}
//	if(paragraph.GetCount() == 0) // TRC 11/02/15: kills formatting of last paragraph in text
//		SetFormat();
	if(oldtab)
		FinishOldTable();
	else
		while(table.GetCount())
			FinishTable();
	EndPart();
	FlushStyles();
}
Example #22
0
// Parses TOC and fills tocTree control
bool HelpViewer::LoadTOC(String const &tocLink)
{
	// TOC is composed by QTF lines with a TOC link and label text
	// lines not containing the TOC link are simply ignored
	// TOC level is represented by number of TABS contained
	// inside a line; zero tabs means toplevel, id 0 of tocTree
	Vector<int>ids;
	ids.Add(0);
	int curLevel = 0;
	int curId = 0;
	TreeCtrl tocTree;
	
	Topic t = GetTopic(tocLink);
	if(IsNull(t.text))
		return false;

	String label = t.label;
	String topic = t.link;

	// sets toc root string from topic ticle
	tocTree.SetRoot(Null, t.title);
	
	// converts QTF to RichTxt, easier to analyze
	RichText txt = ParseQTF(t.text);

	// extract all paragraphs from RichTxt, skip other objects
	for(int iPart = 0; iPart < txt.GetPartCount(); iPart++)
	{
		String tocLine;
		String lineLink;
		if(!txt.IsPara(iPart))
			continue;
		RichPara p = txt.Get(iPart);
		for(int iParaPart = 0; iParaPart < p.GetCount(); iParaPart++)
		{
			RichPara::Part &paraPart = p.part[iParaPart];
			if(paraPart.format.link != "")
				lineLink = paraPart.format.link;
			if(paraPart.NonText())
				continue;
			tocLine += paraPart.text.ToString();
		}
		// if part contains no text nor link to topic stuffs, simply skip it
		if(tocLine == "" || lineLink == "" || !lineLink.StartsWith("topic:"))
			continue;
		
		// now we should count tabls to get TOC indent level
		int level = 0;
		int j;
		while( (j = tocLine.Find(0x09)) >= 0)
		{
			level++;
			tocLine.Remove(j);
		}
		// allows just SINGLE UPPER level change, i.e., deeper ONE level from current
		// for each step; backleveling is possible at any depth
		if(level > curLevel+1)
			return false;
		if(level > curLevel)
		{
			ids.Add(curId);
			curLevel++;
		}
		else while(curLevel > level)
		{
			curLevel--;
			ids.Pop();
		}

		// add the line to correct tree node
		curId = tocTree.Add(ids.Top(), Null, Value(lineLink), Value(tocLine));
	}
	
	// if the tree control is non empty, appends it to the main TOC TreeCtrl
	if(tocTree.GetChildCount(0))
		AppendTOC(tocTree);

	
	// opens all content tree and display first item
	mainTocTree.OpenDeep(0);
	mainTocTree.SetCursor(2);

	// stores first topic at top of stack
	String curLink = mainTocTree.Get();
	stack.Clear();
	stack.Add(curLink);
	tos = 0;
	
	return true;
}
Example #23
0
void RichQtfParser::ReadObject()
{
	Flush();
	RichObject obj;
	if(*term == '#') {
		term++;
	#ifdef CPU_64
		obj = *(RichObject *)stou64(term, &term);
	#else
		obj = *(RichObject *)stou(term, &term);
	#endif
		term++;
	}
	else {
		String type;
		while(IsAlNum(*term) || *term == '_')
			type.Cat(*term++);
		Size sz;
		Key(':');
		sz.cx = ReadNumber();
		bool keepratio = false;
		if(Key('&'))
			keepratio = true;
		else
			Key('*');
		sz.cy = ReadNumber();
		int yd = 0;
		if(Key('/'))
			yd = GetNumber();
		while(*term && (byte)*term < 32)
			term++;
		String odata;
		if(Key('`'))
			while(*term) {
				if(*term == '`') {
					term++;
					if(*term == '`')
						odata.Cat('`');
					else
						break;
				}
				else
				if((byte)*term >= 32)
					odata.Cat(*term);
				term++;
			}
		else
		if(Key('(')) {
			const char *b = term;
			while(*term && *term != ')')
				term++;
			odata = Base64Decode(b, term);
			if(*term == ')')
				term++;
		}
		else {
			StringBuffer data;
			for(;;) {
				while(*term < 32 && *term > 0) term++;
				if((byte)*term >= ' ' && (byte)*term <= 127 || *term == '\0') break;
				byte seven = *term++;
				for(int i = 0; i < 7; i++) {
					while((byte)*term < 32 && (byte)*term > 0) term++;
					if((byte)*term >= ' ' && (byte)*term <= 127 || *term == '\0') break;
					data.Cat((*term++ & 0x7f) | ((seven << 7) & 0x80));
					seven >>= 1;
				}
			}
			odata = data;
		}
		obj.Read(type, odata, sz, context);
		obj.KeepRatio(keepratio);
		obj.SetYDelta(yd);
	}
	paragraph.Cat(obj, format);
}
Example #24
0
void   TopicEditor::FixTopic()
{
	String nest;
	if(!EditText(nest, "Fix topic", "Nest"))
		return;
	CppBase& base = CodeBase();
	int q = base.Find(nest);
	if(q < 0) {
		Exclamation("Nest not found");
		return;
	}
	Array<CppItem>& n = base[q];
	Index<String> natural;
	Vector<String> link;
	for(int i = 0; i < n.GetCount(); i++) {
		const CppItem& m = n[i];
		String nat;
		if(m.virt)
			nat << "virtual ";
		if(m.kind == CLASSFUNCTION || m.kind == CLASSFUNCTIONTEMPLATE)
			nat << "static ";
		nat << m.natural;
		natural.Add(nat);
		link.Add(MakeCodeRef(nest, n[i].qitem));
	}
	RichText result;
	const RichText& txt = editor.Get();
	bool started = false;

	int l, h;
	if(editor.GetSelection(l, h)) {
		l = txt.FindPart(l);
		h = txt.FindPart(h);
	}
	else {
		l = 0;
		h = txt.GetPartCount();
	}

	for(int i = 0; i < txt.GetPartCount(); i++)
		if(txt.IsPara(i)) {
			RichPara p = txt.Get(i);
			if(i >= l && i < h) {
				WString h = p.GetText();
				String nat;
				const wchar *s = h;
				while(*s)
					if(*s == 160 || *s == ' ') {
						nat.Cat(' ');
						while(*s == 160 || *s == ' ') s++;
					}
					else
						nat.Cat(*s++);
				int q = nat.GetCount() ? natural.Find(nat) : -1;
				if(q >= 0) {
					started = true;
					const CppItem& m = n[q];
					RichText h = ParseQTF(styles + ("[s7; &]" + CreateQtf(link[q], n[q].name, m, GetLang(), true)));
					if(h.GetPartCount())
						h.RemovePart(h.GetPartCount() - 1);
					result.CatPick(pick(h));
				}
				else
				if(!started || p.GetLength())
					result.Cat(p);
			}
			else
				result.Cat(p);
		}
		else {
			RichTable b;
			b <<= txt.GetTable(i);
			result.CatPick(pick(b));
		}
	RichPara empty;
	result.Cat(empty);
	editor.BeginOp();
	editor.SetSelection(0, txt.GetLength());
	editor.PasteText(result);
}