1 #include "RichEdit.h"
2 
3 namespace Upp {
4 
5 #define TFILE <RichEdit/RichEdit.t>
6 #include <Core/t.h>
7 
Key(dword key,int count)8 bool FontHeight::Key(dword key, int count)
9 {
10 	if(key == K_ENTER) {
11 		if(!IsError(GetData()))
12 			WhenSelect();
13 		return true;
14 	}
15 	return WithDropChoice<EditDouble>::Key(key, count);
16 }
17 
DotToPt(int dt)18 double RichEdit::DotToPt(int dt)
19 {
20 	return 7200 * minmax(dt, 8, 8000) / 600 / 10 / 10.0;
21 }
22 
PtToDot(double pt)23 int RichEdit::PtToDot(double pt)
24 {
25 	return int((600 * pt + 71) / 72);
26 }
27 
28 struct EditPageDraw : public PageDraw {
29 	virtual Draw& Page(int _page);
30 
31 	Draw&              w;
32 	int                page;
33 	int                x, y;
34 	Size               size;
35 
EditPageDrawUpp::EditPageDraw36 	EditPageDraw(Draw& w) : w(w) { w.Begin(); w.Begin(); page = -1; }
~EditPageDrawUpp::EditPageDraw37 	~EditPageDraw() { w.End(); w.End(); }
38 };
39 
Page(int _page)40 Draw& EditPageDraw::Page(int _page)
41 {
42 	if(page == _page) return w;
43 	page = _page;
44 	w.End();
45 	w.End();
46 	if(size.cy < INT_MAX)
47 		w.Clipoff(0, y + (size.cy + 3) * page + 2, 9999, size.cy);
48 	else
49 		w.Offset(0, y + 2);
50 	w.Offset(x, 0);
51 	return w;
52 }
53 
GetTextRect() const54 Rect RichEdit::GetTextRect() const
55 {
56 	Size sz = GetSize();
57 	if(sz.cy < Zx(16))
58 		sz.cy = Zx(16);
59 	if(sz.cx < Zx(80))
60 		return RectC(0, 0, Zx(48), max(sz.cy, Zy(16)));
61 	int cx = zoom * (sz.cx - 2 * viewborder) / 100;
62 	return RectC((sz.cx - cx) / 2, 0, cx, sz.cy);
63 }
64 
GetZoom() const65 Zoom RichEdit::GetZoom() const
66 {
67 	return Zoom(GetTextRect().Width(), pagesz.cx);
68 }
69 
GetZoomedPage() const70 Size RichEdit::GetZoomedPage() const
71 {
72 	return Size(GetTextRect().Width(), pagesz.cy == INT_MAX ? INT_MAX / 2 : GetZoom() * pagesz.cy);
73 }
74 
GetPosY(PageY py) const75 int  RichEdit::GetPosY(PageY py) const
76 {
77 	return py.page * (GetZoomedPage().cy + 3) + py.y * GetZoom() + 2;
78 }
79 
GetPageY(int y) const80 PageY RichEdit::GetPageY(int y) const
81 {
82 	PageY py;
83 	int q = GetZoomedPage().cy + 3;
84 	py.page = y / q;
85 	py.y = (y % q - 2) / GetZoom();
86 	return py;
87 }
88 
sPaintHotSpot(Draw & w,int x,int y)89 static void sPaintHotSpot(Draw& w, int x, int y)
90 {
91 	w.DrawRect(x, y, DPI(8), DPI(8), LtRed);
92 	DrawFrame(w, x, y, DPI(8), DPI(8), SColorText);
93 }
94 
Paint(Draw & w)95 void RichEdit::Paint(Draw& w)
96 {
97 	Size sz = GetSize();
98 	p_size = sz;
99 	Rect tr = GetTextRect();
100 	Zoom zoom = GetZoom();
101 	w.DrawRect(sz, White);
102 	PageY py = text.GetHeight(pagesz);
103 	{
104 		EditPageDraw pw(w);
105 		pw.x = tr.left;
106 		pw.y = -sb;
107 		pw.size = GetZoomedPage();
108 		if(pagesz.cy == INT_MAX) {
109 			pw.size.cy = INT_MAX;
110 			if(viewborder)
111 				DrawFrame(w, tr.left - 1, (int)sb ? -1 : 0, pw.size.cx + 4, 9999, SColorShadow);
112 		}
113 		else
114 		if(viewborder)
115 			for(int i = 0; i <= py.page; i++)
116 				DrawFrame(w, tr.left - 1, i * (pw.size.cy + 3) + 1 - sb,
117 				          pw.size.cx + 4, pw.size.cy + 2, SColorShadow);
118 		PaintInfo pi = paint_info;
119 		pi.context = context;
120 		pi.zoom = zoom;
121 		pi.top = GetPageY(sb);
122 		pi.bottom = GetPageY(sb + sz.cy);
123 		pi.usecache = true;
124 		pi.sizetracking = sizetracking;
125 		pi.showcodes = showcodes;
126 		pi.showlabels = !IsNull(showcodes) && viewborder >= 16;
127 		pi.hyperlink = LtBlue; // because we have white paper even in dark mode
128 
129 		if(spellcheck)
130 			pi.spellingchecker = SpellParagraph;
131 		if(IsSelection()) {
132 			if(tablesel) {
133 				pi.tablesel = tablesel;
134 				pi.cells = cells;
135 			}
136 			else {
137 				pi.sell = begtabsel ? -1 : min(cursor, anchor);
138 				pi.selh = max(cursor, anchor);
139 			}
140 		}
141 		text.Paint(pw, pagesz, pi);
142 	}
143 	w.DrawRect(tr.left, GetPosY(py) - sb, 20, 3, showcodes);
144 	if(objectpos >= 0) {
145 		Rect r = objectrect;
146 		r.Offset(tr.left, -sb);
147 		DrawFrame(w, r, Black());
148 		r.Deflate(DPI(1));
149 		DrawFatFrame(w, r, White(), DPI(2));
150 		r.Deflate(DPI(2));
151 		DrawFrame(w, r, Black());
152 		r.Deflate(DPI(1));
153 		sPaintHotSpot(w, r.left + r.Width() / 2 - DPI(3), r.bottom - DPI(7));
154 		sPaintHotSpot(w, r.right - DPI(7), r.bottom - DPI(7));
155 		sPaintHotSpot(w, r.right - DPI(7), r.top + r.Height() / 2 - DPI(3));
156 		w.Clip(r);
157 		w.End();
158 	}
159 	else
160 	if(paintcarect)
161 		w.DrawRect(GetCaretRect(), InvertColor);
162 	if(!IsNull(dropcaret))
163 		DrawTiles(w, dropcaret.OffsetedVert(-sb), CtrlImg::checkers());
164 	scroller.Set(sb);
165 }
166 
GetHotSpot(Point p) const167 int RichEdit::GetHotSpot(Point p) const
168 {
169 	if(objectpos < 0) return -1;
170 	Rect r = objectrect;
171 	r.Offset(GetTextRect().left, -sb);
172 	r.Deflate(DPI(4), DPI(4));
173 	if(RectC(r.right - DPI(7), r.bottom - DPI(7), DPI(8), DPI(12)).Contains(p))
174 		return 0;
175 	if(RectC(r.left + r.Width() / 2 - DPI(3), r.bottom - DPI(7), DPI(12), DPI(12)).Contains(p))
176 		return 1;
177 	if(RectC(r.right - DPI(7), r.top + r.Height() / 2 - DPI(3), DPI(12), DPI(8)).Contains(p))
178 		return 2;
179 	return -1;
180 }
181 
SetZsc()182 void RichEdit::SetZsc()
183 {
184 	zsc = (int)sb / GetZoom();
185 }
186 
SetSb()187 void RichEdit::SetSb()
188 {
189 	sb.SetTotal(GetPosY(text.GetHeight(pagesz)) + 10);
190 }
191 
Scroll()192 void RichEdit::Scroll()
193 {
194 	scroller.Scroll(*this, GetSize(), sb);
195 	PlaceCaret();
196 }
197 
EndSizeTracking()198 void RichEdit::EndSizeTracking()
199 {
200 	if(sizetracking) {
201 		sizetracking = false;
202 		Refresh();
203 	}
204 }
205 
FixObjectRect()206 void RichEdit::FixObjectRect()
207 {
208 	if(objectpos >= 0) {
209 		Rect r = GetObjectRect(objectpos);
210 		if(r != objectrect) {
211 			objectrect = r;
212 			Refresh(objectrect);
213 		}
214 	}
215 }
216 
Floating(double zoomlevel_)217 RichEdit& RichEdit::Floating(double zoomlevel_)
218 {
219 	floating_zoom = zoomlevel_;
220 	RefreshLayoutDeep();
221 	return *this;
222 }
223 
Layout()224 void RichEdit::Layout()
225 {
226 	Size sz = GetTextRect().GetSize();
227 	if(!IsNull(floating_zoom)) {
228 		Zoom m = GetRichTextStdScreenZoom();
229 		SetPage(Size(int(1 / floating_zoom * m.d / m.m * sz.cx), INT_MAX));
230 	}
231 	sb.SetPage(sz.cy > 10 ? sz.cy - 4 : sz.cy);
232 	SetupRuler();
233 	SetSb();
234 	sb = zsc * GetZoom();
235 	PlaceCaret();
236 	if(GetSize() != p_size) {
237 		sizetracking = true;
238 		KillSetTimeCallback(250, THISBACK(EndSizeTracking), TIMEID_ENDSIZETRACKING);
239 	}
240 	FixObjectRect();
241 }
242 
GetCaretRect(const RichCaret & pr) const243 Rect RichEdit::GetCaretRect(const RichCaret& pr) const
244 {
245 	Zoom zoom = GetZoom();
246 	Rect tr = GetTextRect();
247 	Rect r = RectC(pr.left * zoom + tr.left, GetPosY(pr) + (pr.lineascent - pr.caretascent) * zoom - sb,
248 	               overwrite && GetChar(cursor) != '\n' ? pr.Width() * zoom
249 	                         : (pr.caretascent + pr.caretdescent) * zoom > 20 ? 2 : 1,
250 	               (pr.caretascent + pr.caretdescent) * zoom);
251 	if(r.right > tr.right)
252 		return Rect(tr.right - r.Width(), r.top, tr.right, r.bottom);
253 	return r;
254 }
255 
GetCaretRect() const256 Rect RichEdit::GetCaretRect() const
257 {
258 	return GetCaretRect(text.GetCaret(cursor, pagesz));
259 }
260 
PlaceCaret()261 Rect RichEdit::PlaceCaret()
262 {
263 	Zoom zoom = GetZoom();
264 	Rect rr = Rect(zoom * cursorc.left, GetPosY(cursorc), zoom * cursorc.right,
265 	               GetPosY(PageY(cursorc.page, cursorc.bottom)));
266 	if(objectpos >= 0) {
267 		KillCaret();
268 		return rr;
269 	}
270 	if(!IsNull(objectrect)) {
271 		objectrect = Null;
272 		Refresh();
273 	}
274 	if(IsSelection())
275 		KillCaret();
276 	else
277 		SetCaret(GetCaretRect(cursorc));
278 	return rr;
279 }
280 
SetupRuler()281 void RichEdit::SetupRuler()
282 {
283 	Zoom zoom = GetZoom();
284 	static struct Tl {
285 		double grid;
286 		int    numbers;
287 		double numbermul;
288 		int    marks;
289 	}
290 	tl[] = {
291 		{ 25, 20, 25, 4 },
292 		{ 600 / 72 * 4, 9, 4, 1000 },
293 		{ 600 / 10, 10, 1 / 10.0, 5 },
294 		{ 600 / 25.4, 10, 1, 5 },
295 		{ 600 / 25.4, 10, 1 / 10.0, 5 },
296 	};
297 	const Tl& q = tl[unit];
298 	ruler.SetLayout(GetTextRect().left + zoom * cursorc.textpage.left, cursorc.textpage.Width(),
299 	                zoom, q.grid, q.numbers, q.numbermul, q.marks);
300 }
301 
SetupUnits()302 void RichEdit::SetupUnits()
303 {
304 	WithUnitLayout<TopWindow> d;
305 	CtrlLayoutOKCancel(d, t_("Units"));
306 	d.accels <<= THISBACK(StyleKeys);
307 	for(int i = 1; i <= 10; i++)
308 		d.zoom.Add(10 * i, Format(t_("%d%% of width"), 10 * i));
309 	CtrlRetriever r;
310 	r(d.unit, unit)(d.showcodes, showcodes)(d.zoom, zoom);
311 	if(d.Execute() == IDOK) {
312 		r.Retrieve();
313 		Refresh();
314 		FinishNF();
315 	}
316 }
317 
ZoomView(int d)318 void RichEdit::ZoomView(int d)
319 {
320 	zoom = clamp(zoom + d * 10, 10, 100);
321 	Refresh();
322 	FinishNF();
323 }
324 
GetNearestPos(int x,PageY py)325 int  RichEdit::GetNearestPos(int x, PageY py)
326 {
327 	int c = text.GetPos(x, py, pagesz);
328 	String dummy;
329 	RichPos p = text.GetRichPos(c);
330 	if(c >= text.GetLength() - 1 || c < 0 || p.object || p.field
331 	   || p.table && (p.posincell == 0 || p.posincell == p.celllen))
332 		return c;
333 	Rect r1 = text.GetCaret(c, pagesz);
334 	Rect r2 = text.GetCaret(c + 1, pagesz);
335 	return r1.top == r2.top && x - r1.left > r2.left - x ? c + 1 : c;
336 }
337 
GetX(int x)338 int RichEdit::GetX(int x)
339 {
340 	return (x - GetTextRect().left) / GetZoom();
341 }
342 
GetSnapX(int x)343 int RichEdit::GetSnapX(int x)
344 {
345 	return GetX(x) / 32 * 32;
346 }
347 
GetPagePoint(Point p,PageY & py,int & x)348 void RichEdit::GetPagePoint(Point p, PageY& py, int& x)
349 {
350 	py = GetPageY(p.y + sb);
351 	x = GetX(p.x);
352 }
353 
GetMousePos(Point p)354 int  RichEdit::GetMousePos(Point p) {
355 	PageY py;
356 	int    x;
357 	GetPagePoint(p, py, x);
358 	return GetNearestPos(x, py);
359 }
360 
GetObjectRect(int pos) const361 Rect RichEdit::GetObjectRect(int pos) const {
362 	Zoom zoom = GetZoom();
363 	RichCaret pr = text.GetCaret(pos, pagesz);
364 	Rect r = Rect(zoom * pr.left,
365 	              GetPosY(PageY(pr.page, pr.top + pr.lineascent - pr.objectcy + pr.objectyd)),
366 	              zoom * pr.right,
367 	              GetPosY(PageY(pr.page, pr.top + pr.lineascent + pr.objectyd)));
368 	return r;
369 }
370 
Print()371 bool RichEdit::Print()
372 {
373 	text.SetFooter(footer);
374 	text.PrintNoLinks(nolinks);
375 	return UPP::Print(text, pagesz, cursorc.page);
376 }
377 
378 struct DisplayFont : public Display {
PaintUpp::DisplayFont379 	void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
380 	{
381 		Font fnt;
382 		fnt.Face((int)q);
383 		fnt.Height(r.Height() - Zy(4));
384 		w.DrawRect(r, paper);
385 		w.DrawText(r.left, r.top + (r.Height() - fnt.Info().GetHeight()) / 2,
386 		           Font::GetFaceName((int)q), fnt, ink);
387 	}
388 };
389 
390 struct ValueDisplayFont : public Display {
PaintUpp::ValueDisplayFont391 	void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper, dword style) const
392 	{
393 		w.DrawRect(r, paper);
394 		w.DrawText(r.left, r.top + (r.Height() - StdFont().Info().GetHeight()) / 2,
395 		           Font::GetFaceName((int)q), StdFont(), ink);
396 	}
397 };
398 
Clear()399 void RichEdit::Clear()
400 {
401 	undo.Clear();
402 	redo.Clear();
403 	text.Clear();
404 	Reset();
405 	RichPara h;
406 	h.format.language = GetCurrentLanguage();
407 	text.Cat(h);
408 	Refresh();
409 	Finish();
410 	ReadStyles();
411 	SetModify();
412 	modified = true;
413 	zsc = 0;
414 }
415 
SetupLanguage(Vector<int> && _lng)416 void RichEdit::SetupLanguage(Vector<int>&& _lng)
417 {
418 	Vector<int>& lng = const_cast<Vector<int>&>(_lng);
419 	Sort(lng);
420 	language.ClearList();
421 	for(int i = 0; i < lng.GetCount(); i++)
422 		language.Add(lng[i], lng[i] ? LNGAsText(lng[i]) : String(t_("None")));
423 }
424 
Pick(RichText pick_ t)425 void RichEdit::Pick(RichText pick_ t)
426 {
427 	Clear();
428 	text = pick(t);
429 	if(text.GetPartCount() == 0)
430 		text.Cat(RichPara());
431 	ReadStyles();
432 	EndSizeTracking();
433 	SetupLanguage(text.GetAllLanguages());
434 	Move(0);
435 	Update();
436 }
437 
GetData() const438 Value RichEdit::GetData() const
439 {
440 	return AsQTF(text);
441 }
442 
SetData(const Value & v)443 void  RichEdit::SetData(const Value& v)
444 {
445 	Pick(ParseQTF((String)v, 0, context));
446 }
447 
Serialize(Stream & s)448 void  RichEdit::Serialize(Stream& s)
449 {
450 	int version = 0;
451 	s / version;
452 	String h;
453 	if(s.IsStoring())
454 		h = AsQTF(text);
455 	s % h;
456 	if(s.IsLoading())
457 		Pick(ParseQTF(h, 0, context));
458 }
459 
460 int RichEdit::fh[] = {
461 	6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 42, 48, 60, 72, 0
462 };
463 
FontFaces(const Vector<int> & ff)464 RichEdit& RichEdit::FontFaces(const Vector<int>& ff)
465 {
466 	ffs <<= ff;
467 	face.ClearList();
468 	for(int i = 0; i < ff.GetCount(); i++)
469 		face.Add(ff[i]);
470 	return *this;
471 }
472 
SetupFaceList(DropList & face)473 void SetupFaceList(DropList& face)
474 {
475 	face.ValueDisplay(Single<ValueDisplayFont>());
476 	face.SetDisplay(Single<DisplayFont>());
477 }
478 
SpellCheck()479 void RichEdit::SpellCheck()
480 {
481 	spellcheck = !spellcheck;
482 	Refresh();
483 	RefreshBar();
484 }
485 
SerializeSettings(Stream & s)486 void RichEdit::SerializeSettings(Stream& s)
487 {
488 	int version = 3;
489 	s / version;
490 	s % unit;
491 	s % showcodes;
492 	if(version >= 1)
493 		s % zoom;
494 	s % spellcheck;
495 	s % findreplace.find;
496 	findreplace.find.SerializeList(s);
497 	s % findreplace.replace;
498 	findreplace.replace.SerializeList(s);
499 	s % findreplace.wholeword;
500 	s % findreplace.ignorecase;
501 	RefreshBar();
502 	imagefs.Serialize(s);
503 	if(version >= 3)
504 		for(int i = 0; i < 20; i++) {
505 			StyleKey& k = stylekey[i];
506 			s % k.styleid % k.stylename % k.face % k.height % k.ink % k.paper;
507 		}
508 }
509 
Reset()510 void RichEdit::Reset()
511 {
512 	undoserial = 0;
513 	incundoserial = false;
514 
515 	objectpos = -1;
516 	objectrect = Null;
517 	sizetracking = true;
518 
519 	anchor = cursor = 0;
520 	gx = 0;
521 	oselh = osell = 0;
522 
523 	RichPara::Format pmt;
524 	formatinfo.Set(pmt);
525 
526 	tabmove.table = 0;
527 }
528 
PickUndoInfo()529 RichEdit::UndoInfo RichEdit::PickUndoInfo()
530 {
531 	UndoInfo f;
532 	f.undoserial = undoserial;
533 	f.undo = pick(undo);
534 	f.redo = pick(redo);
535 	Clear();
536 	return f;
537 }
538 
SetPickUndoInfo(UndoInfo pick_ f)539 void RichEdit::SetPickUndoInfo(UndoInfo pick_ f)
540 {
541 	undoserial = f.undoserial;
542 	incundoserial = true;
543 	undo = pick(f.undo);
544 	redo = pick(f.redo);
545 	Finish();
546 }
547 
Serialize(Stream & s)548 void RichEdit::PosInfo::Serialize(Stream& s)
549 {
550 	int version = 2;
551 	s / version;
552 	s % cursor % anchor % zsc % begtabsel;
553 	if(version == 0)
554 		zsc = 0;
555 }
556 
GetPosInfo() const557 RichEdit::PosInfo RichEdit::GetPosInfo() const
558 {
559 	PosInfo f;
560 	f.cursor = cursor;
561 	f.anchor = anchor;
562 	f.begtabsel = begtabsel;
563 	f.zsc = zsc;
564 	return f;
565 }
566 
SetPosInfo(const PosInfo & f)567 void RichEdit::SetPosInfo(const PosInfo& f)
568 {
569 	int l = text.GetLength();
570 	cursor = min(l, f.cursor);
571 	anchor = min(l, f.anchor);
572 	begtabsel = f.begtabsel;
573 	if(begtabsel)
574 		anchor = 0;
575 	Finish();
576 	zsc = f.zsc;
577 	Layout();
578 }
579 
DoRefreshBar()580 void RichEdit::DoRefreshBar()
581 {
582 	WhenRefreshBar();
583 }
584 
RefreshBar()585 void RichEdit::RefreshBar()
586 {
587 	KillTimeCallback(TIMEID_REFRESHBAR);
588 	SetTimeCallback(0, THISBACK(DoRefreshBar), TIMEID_REFRESHBAR);
589 }
590 
StdLinkDlg(String & s,WString &)591 void StdLinkDlg(String& s, WString&)
592 {
593 	EditText(s, t_("Hyperlink"), t_("Hyperlink"), CharFilterAscii128, 1000);
594 }
595 
StdLabelDlg(String & s)596 void StdLabelDlg(String& s)
597 {
598 	EditText(s, t_("Paragraph label"), t_("Label"), CharFilterAscii128, 1000);
599 }
600 
StdIndexEntryDlg(String & s)601 void StdIndexEntryDlg(String& s)
602 {
603 	EditText(s, t_("Index Entry"), t_("Index entry"), CharFilterAscii128, 1000);
604 }
605 
RichEdit()606 RichEdit::RichEdit()
607 {
608 	floating_zoom = Null;
609 
610 	Unicode();
611 	BackPaint();
612 
613 	viewborder = Zx(16);
614 
615 	face.NoWantFocus();
616 	height.NoWantFocus();
617 	style.NoWantFocus();
618 	language.NoWantFocus();
619 
620 	setstyle = &style.InsertButton(0).SetMonoImage(CtrlImg::smallleft()).Tip(t_("Store as style"));
621 	setstyle->WhenClick = THISBACK(SetStyle);
622 	style.InsertButton(0).SetMonoImage(RichEditImg::ManageStyles()).Tip(t_("Style manager"))
623 	     .WhenClick = THISBACK(Styles);
624 	style.Tip(t_("Style"));
625 
626 	style <<= THISBACK(Style);
627 
628 	WhenBar = THISBACK(StdBar);
629 
630 	pagesz = Size(3968, 6074);
631 	unit = UNIT_POINT;
632 	zoom = 100;
633 	Clear();
634 
635 	context = NULL;
636 
637 	nolinks = false;
638 
639 	showcodes = LtBlue;
640 	spellcheck = true;
641 
642 	overwrite = false;
643 
644 	sb.WhenScroll = THISBACK(Scroll);
645 	sb.SetLine(16);
646 	Layout();
647 	SetSb();
648 
649 	adjustunits.Image(RichEditImg::AdjustUnits());
650 	adjustunits <<= THISBACK(SetupUnits);
651 	ruler.Add(adjustunits.RightPosZ(4, 16).VSizePosZ(2, 2));
652 
653 	undosteps = 500;
654 
655 	AddFrame(ViewFrame());
656 	AddFrame(ruler);
657 	AddFrame(sb);
658 	RefreshBar();
659 
660 	ruler.WhenBeginTrack = THISBACK(BeginRulerTrack);
661 	ruler.WhenTrack = THISBACK(RulerTrack);
662 	ruler.WhenEndTrack = THISBACK(ReadFormat);
663 	ruler.WhenLeftDown = THISBACK(AddTab);
664 	ruler.WhenRightDown = THISBACK(TabMenu);
665 
666 	SetupFaceList(face);
667 	face <<= THISBACK(SetFace);
668 	face.Tip(t_("Font face"));
669 	Vector<int> ff;
670 	ff.Add(Font::ARIAL);
671 	ff.Add(Font::ROMAN);
672 	ff.Add(Font::COURIER);
673 	FontFaces(ff);
674 
675 	language <<= THISBACK(SetLanguage);
676 	language.Tip(t_("Language"));
677 	language.WhenClick = THISBACK(Language);
678 	language.Add(0, t_("None"));
679 
680 	for(int i = 0; fh[i]; i++)
681 		height.AddList(fh[i]);
682 	height.WhenSelect = THISBACK(SetHeight);
683 	height.Tip(t_("Font height"));
684 
685 	hyperlink <<= THISBACK(Hyperlink);
686 	hyperlink.NoWantFocus();
687 	label <<= THISBACK(Label);
688 	indexentry << THISBACK(IndexEntry);
689 	indexentry.NoWantFocus();
690 
691 	gotolabel.SetMonoImage(RichEditImg::GoTo());
692 	label.AddFrame(gotolabel);
693 	gotolabel.Tip(t_("Go to label"));
694 	gotolabel <<= THISBACK(GotoLbl);
695 	gotolabel.NoWantFocus();
696 
697 	gotoentry.SetMonoImage(RichEditImg::GoTo());
698 	indexentry.AddFrame(gotoentry);
699 	gotoentry.Tip(t_("Go to index entry"));
700 	gotoentry <<= THISBACK(GotoEntry);
701 
702 	gototable.Normal();
703 	gototable.AddIndex();
704 	gototable.AddIndex();
705 
706 	gototable.WhenSelect = THISBACK(Goto);
707 
708 	ink.ColorImage(RichEditImg::InkColor())
709 	   .NullImage(RichEditImg::NullInkColor())
710 	   .StaticImage(RichEditImg::ColorA());
711 	ink.NotNull();
712 	paper.ColorImage(RichEditImg::PaperColor())
713 	     .NullImage(RichEditImg::NullPaperColor())
714 	     .StaticImage(RichEditImg::ColorA());
715 	ink <<= THISBACK(SetInk);
716 	ink.Tip(t_("Text color"));
717 	paper <<= THISBACK(SetPaper);
718 	paper.Tip(t_("Background color"));
719 
720 	ReadStyles();
721 
722 	paintcarect = false;
723 
724 	CtrlLayoutOKCancel(findreplace, t_("Find / Replace"));
725 	findreplace.cancel <<= callback(&findreplace, &TopWindow::Close);
726 	findreplace.ok <<= THISBACK(Find);
727 	findreplace.amend <<= THISBACK(Replace);
728 	notfoundfw = found = false;
729 	findreplace.NoCenter();
730 
731 	WhenHyperlink = callback(StdLinkDlg);
732 	WhenLabel = callback(StdLabelDlg);
733 	WhenIndexEntry = callback(StdIndexEntryDlg);
734 
735 	p_size = Size(-1, -1);
736 
737 	useraction = modified = false;
738 	ClearModify();
739 	Finish();
740 
741 	imagefs.Type("Images (*.png *.gif *.jpg *.bmp *.svg)", "*.png *.gif *.jpg *.bmp *.svg");
742 
743 	singleline = false;
744 
745 	clipzoom = Zoom(1, 1);
746 
747 	bullet_indent = 150;
748 
749 	persistent_findreplace = true;
750 
751 	ignore_physical_size = false;
752 }
753 
~RichEdit()754 RichEdit::~RichEdit() {}
755 
TheBar(Bar & bar)756 void RichEditWithToolBar::TheBar(Bar& bar)
757 {
758 	DefaultBar(bar, extended);
759 }
760 
RefreshBar()761 void RichEditWithToolBar::RefreshBar()
762 {
763 	toolbar.Set(THISBACK(TheBar));
764 }
765 
EvaluateFields()766 void RichEdit::EvaluateFields()
767 {
768 	WhenStartEvaluating();
769 	text.EvaluateFields(vars);
770 	Finish();
771 }
772 
RichEditWithToolBar()773 RichEditWithToolBar::RichEditWithToolBar()
774 {
775 	InsertFrame(0, toolbar);
776 	WhenRefreshBar = callback(this, &RichEditWithToolBar::RefreshBar);
777 	extended = true;
778 }
779 
780 }
781