1 #include "RichEdit.h"
2 #include <Painter/Painter.h>
3
4 namespace Upp {
5
InsertImage()6 void RichEdit::InsertImage()
7 {
8 if(!imagefs.ExecuteOpen(t_("Open image from file")))
9 return;
10 String fn = ~imagefs;
11 if(GetFileLength(fn) > 17000000) {
12 Exclamation("Image is too large!");
13 return;
14 }
15 String data = LoadFile(fn);
16 StringStream ss(data);
17 if(!StreamRaster::OpenAny(ss) && !IsSVG(data)) {
18 Exclamation(Format(t_("Unsupported image format in file [* \1%s\1]."), ~imagefs));
19 return;
20 }
21 RichText clip;
22 RichPara p;
23 p.Cat(CreateRawImageObject(data), formatinfo);
24 clip.Cat(p);
25 ClipPaste(clip, "image/raw");
26 }
27
Accept(PasteClip & d,RichText & clip,String & fmt)28 bool RichEdit::Accept(PasteClip& d, RichText& clip, String& fmt)
29 {
30 if(IsReadOnly())
31 return false;
32 if(AcceptFiles(d)) {
33 Vector<String> s = GetFiles(d);
34 if(s.GetCount()) {
35 String fn = s[0];
36 String ext = ToLower(GetFileExt(fn));
37 if(findarg(ext, ".png", ".jpg", ".jpeg", ".gif", ".tif", ".tiff", ".svg") >= 0) {
38 if(d.Accept() && GetFileLength(fn) < 17000000) {
39 String data = LoadFile(fn);
40 StringStream ss(data);
41 if(StreamRaster::OpenAny(ss) || ext == ".svg" && IsSVG(LoadFile(fn))) {
42 RichPara p;
43 p.Cat(CreateRawImageObject(data), formatinfo);
44 clip.Cat(p);
45 fmt = "files";
46 }
47 return true;
48 }
49 return false;
50 }
51 }
52 d.Reject();
53 }
54 if(d.Accept("image/x-inkscape-svg")) {
55 RichPara p;
56 p.Cat(CreateRawImageObject(~d), formatinfo);
57 clip.Cat(p);
58 fmt = "files";
59 }
60 if(d.Accept("text/QTF")) {
61 fmt = "text/QTF";
62 clip = ParseQTF(~d, 0, context);
63 return true;
64 }
65 if(d.Accept(ClipFmtsRTF())) {
66 fmt = ClipFmtsRTF();
67 clip = ParseRTF(~d);
68 return true;
69 }
70 for(int i = 0; i < RichObject::GetTypeCount(); i++) {
71 RichObjectType& rt = RichObject::GetType(i);
72 if(rt.Accept(d)) {
73 Value data = rt.Read(d);
74 if(!IsNull(data)) {
75 RichPara p;
76 RichObject o = RichObject(&rt, data, pagesz);
77 p.Cat(o, formatinfo);
78 clip.Cat(p);
79 fmt = o.GetTypeName();
80 }
81 return true;
82 }
83 }
84 if(AcceptText(d)) {
85 fmt = "text/plain";
86 clip = AsRichText(GetWString(d), formatinfo);
87 return true;
88 }
89 return false;
90 }
91
ClipPaste(RichText & clip,const String & fmt)92 void RichEdit::ClipPaste(RichText& clip, const String& fmt)
93 {
94 clip.ApplyZoom(clipzoom.Reciprocal());
95 PasteFilter(clip, fmt);
96 NextUndo();
97 if(clip.GetPartCount() == 1 && clip.IsTable(0)) {
98 CancelSelection();
99 if(cursorp.table) {
100 NextUndo();
101 SaveTable(cursorp.table);
102 text.PasteTable(cursorp.table, cursorp.cell, clip.GetTable(0));
103 Finish();
104 return;
105 }
106 }
107 clip.Normalize();
108 PasteText(clip);
109 }
110
DragAndDrop(Point p,PasteClip & d)111 void RichEdit::DragAndDrop(Point p, PasteClip& d)
112 {
113 int dropcursor = GetMousePos(p);
114 if(dropcursor >= 0) {
115 RichText clip;
116 String fmt;
117 if(Accept(d, clip, fmt)) {
118 NextUndo();
119 int a = sb;
120 int c = dropcursor;
121 if(InSelection(c)) {
122 if(!IsReadOnly())
123 RemoveSelection();
124 if(IsDragAndDropSource())
125 d.SetAction(DND_COPY);
126 }
127 int sell, selh;
128 if(GetSelection(sell, selh) && d.GetAction() == DND_MOVE && IsDragAndDropSource()) {
129 if(c > sell)
130 c -= selh - sell;
131 if(!IsReadOnly())
132 RemoveSelection();
133 d.SetAction(DND_COPY);
134 }
135 Move(c);
136 clip.Normalize();
137 ClipPaste(clip, fmt);
138 sb = a;
139 Select(c, clip.GetLength());
140 SetFocus();
141 Action();
142 return;
143 }
144 }
145 if(!d.IsAccepted())
146 dropcursor = -1;
147 Rect r = Null;
148 if(dropcursor >= 0 && dropcursor < text.GetLength()) {
149 RichCaret pr = text.GetCaret(dropcursor, pagesz);
150 Zoom zoom = GetZoom();
151 Rect tr = GetTextRect();
152 r = RectC(pr.left * zoom + tr.left - 1,
153 GetPosY(pr) + (pr.lineascent - pr.caretascent) * zoom,
154 2, (pr.caretascent + pr.caretdescent) * zoom);
155 }
156 if(r != dropcaret) {
157 RefreshDropCaret();
158 dropcaret = r;
159 RefreshDropCaret();
160 }
161 }
162
DragRepeat(Point p)163 void RichEdit::DragRepeat(Point p)
164 {
165 sb = (int)sb + GetDragScroll(this, p, 16).y;
166 }
167
RefreshDropCaret()168 void RichEdit::RefreshDropCaret()
169 {
170 Refresh(dropcaret.OffsetedVert(-sb));
171 }
172
Paste()173 void RichEdit::Paste()
174 {
175 if(IsReadOnly())
176 return;
177 RichText clip;
178 PasteClip d = Clipboard();
179 String fmt;
180 if(!Accept(d, clip, fmt))
181 return;
182 ClipPaste(clip, fmt);
183 }
184
DragLeave()185 void RichEdit::DragLeave()
186 {
187 RefreshDropCaret();
188 dropcaret.Clear();
189 }
190
sRTF(const Value & data)191 static String sRTF(const Value& data)
192 {
193 const RichText& txt = ValueTo<RichText>(data);
194 return EncodeRTF(txt);
195 }
196
sQTF(const Value & data)197 static String sQTF(const Value& data)
198 {
199 const RichText& txt = ValueTo<RichText>(data);
200 return AsQTF(txt);
201 }
202
ZoomClip(RichText & text) const203 void RichEdit::ZoomClip(RichText& text) const
204 {
205 text.ApplyZoom(clipzoom);
206 }
207
AppendClipboard(RichText && txt)208 void AppendClipboard(RichText&& txt)
209 {
210 AppendClipboardUnicodeText(txt.GetPlainText());
211 Value clip = RawPickToValue(pick(txt));
212 AppendClipboard("text/QTF", clip, sQTF);
213 AppendClipboard(ClipFmtsRTF(), clip, sRTF);
214 }
215
Copy()216 void RichEdit::Copy()
217 {
218 RichText txt;
219 if(IsSelection())
220 txt = GetSelection();
221 else if(objectpos >= 0)
222 txt = text.Copy(cursor, 1);
223 else {
224 BeepExclamation();
225 return;
226 }
227 ZoomClip(txt);
228 ClearClipboard();
229 AppendClipboard(pick(txt));
230 if(objectpos >= 0) {
231 RichObject o = GetObject();
232 Vector<String> v = Split(o.GetType().GetClipFmts(), ';');
233 for(int i = 0; i < v.GetCount(); i++)
234 AppendClipboard(v[i], o.GetType().GetClip(o.GetData(), v[i]));
235 }
236 }
237
GetSelectionData(const String & fmt) const238 String RichEdit::GetSelectionData(const String& fmt) const
239 {
240 String f = fmt;
241 if(IsSelection()) {
242 RichText clip = GetSelection();
243 ZoomClip(clip);
244 if(f == "text/QTF")
245 return AsQTF(clip);
246 if(InScList(f, ClipFmtsRTF()))
247 return EncodeRTF(clip);
248 return GetTextClip(clip.GetPlainText(), fmt);
249 }
250 /* else
251 if(objectpos >= 0) {
252 RichObject o = GetObject();
253 if(InScList(fmt, o.GetType().GetClipFmts()))
254 return o.GetType().GetClip(o.GetData(), fmt);
255 }*/
256 return Null;
257 }
258
LeftDrag(Point p,dword flags)259 void RichEdit::LeftDrag(Point p, dword flags)
260 {
261 int c = GetMousePos(p);
262 Size ssz = StdSampleSize();
263 if(!HasCapture() && InSelection(c)) {
264 RichText sample = GetSelection(5000);
265 sample.ApplyZoom(Zoom(1, 8));
266 ImageDraw iw(ssz);
267 iw.DrawRect(0, 0, ssz.cx, ssz.cy, White);
268 sample.Paint(iw, 0, 0, 128);
269 NextUndo();
270 if(DoDragAndDrop(String().Cat() << "text/QTF;" << ClipFmtsRTF() << ";" << ClipFmtsText(),
271 ColorMask(iw, White)) == DND_MOVE && !IsReadOnly()) {
272 RemoveSelection();
273 Action();
274 }
275 }
276 /* else
277 if(objectpos >= 0 && c == objectpos) {
278 ReleaseCapture();
279 RichObject o = GetObject();
280 Size sz = o.GetPhysicalSize();
281 NextUndo();
282 if(DoDragAndDrop(o.GetType().GetClipFmts(),
283 o.ToImage(Size(ssz.cx, sz.cy * ssz.cx / sz.cx))) == DND_MOVE
284 && objectpos >= 0) {
285 if(droppos > objectpos)
286 droppos--;
287 Remove(objectpos, 1);
288 }
289 Move(droppos);
290 SetObjectPos(droppos);
291 }*/
292 }
293
MiddleDown(Point p,dword flags)294 void RichEdit::MiddleDown(Point p, dword flags)
295 {
296 RichText clip;
297 if(IsReadOnly())
298 return;
299 String fmt;
300 if(Accept(Selection(), clip, fmt)) {
301 selclick = false;
302 LeftDown(p, flags);
303 ClipPaste(clip, fmt);
304 }
305 }
306
307 }
308