|
1 /* |
|
2 * Copyright (c) 2000-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "EditorPlainTextCommands.h" |
|
20 #include "AssertFileAndLine.h" |
|
21 #include <txtetext.h> |
|
22 #include <txtclipboard.h> |
|
23 |
|
24 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
25 #include "txtfmlyr_internal.h" |
|
26 #endif |
|
27 using namespace UndoSystem; |
|
28 |
|
29 ///////////////////////// |
|
30 // // |
|
31 // Internal Commands // |
|
32 // // |
|
33 ///////////////////////// |
|
34 |
|
35 TUid CEditorCommand::FamilyUid() const { return TUid::Uid(KUndoDllUid); } |
|
36 |
|
37 CEditorCommandInsertTextAndFormat* |
|
38 CEditorCommand::CastToCEditorCommandInsertTextAndFormat() { return 0; } |
|
39 CEditorCommandDeleteText* |
|
40 CEditorCommand::CastToCEditorCommandDeleteText() { return 0; } |
|
41 CEditorCommandInsertPlainText* |
|
42 CEditorCommand::CastToCEditorCommandInsertPlainText() { return 0; } |
|
43 CEditorCommandDeletePlainText* |
|
44 CEditorCommand::CastToCEditorCommandDeletePlainText() { return 0; } |
|
45 CEditorCommandDeleteCharFormat* |
|
46 CEditorCommand::CastToCEditorCommandDeleteCharFormat() { return 0; } |
|
47 CEditorCommandDeleteParFormat* |
|
48 CEditorCommand::CastToCEditorCommandDeleteParFormat() { return 0; } |
|
49 |
|
50 ///////////////////////////////// |
|
51 // // |
|
52 // Command coalesce function // |
|
53 // // |
|
54 ///////////////////////////////// |
|
55 |
|
56 CCommand* UndoSystem::CoalesceL(CCommand* aLeft, CCommand* aRight) |
|
57 { |
|
58 if (!aRight) |
|
59 return aLeft; |
|
60 if (!aLeft) |
|
61 return aRight; |
|
62 |
|
63 CleanupStack::PushL(aRight); |
|
64 CBatchCommand* batch = aLeft->Batch(); |
|
65 if (batch) |
|
66 { |
|
67 batch->PrepareToPushL(aRight); |
|
68 batch->Push(aRight); |
|
69 CleanupStack::Pop(aRight); |
|
70 return batch; |
|
71 } |
|
72 ASSERT(aLeft->Single()); |
|
73 batch = CBatchCommand::NewL(); |
|
74 CleanupStack::PushL(batch); |
|
75 batch->PrepareToPushL(aLeft); |
|
76 batch->Push(aLeft); |
|
77 batch->PrepareToPushL(aRight); |
|
78 batch->Push(aRight); |
|
79 CleanupStack::Pop(batch); |
|
80 CleanupStack::Pop(aRight); |
|
81 return batch; |
|
82 } |
|
83 |
|
84 /** |
|
85 * Command for deleting plain text. |
|
86 * |
|
87 * @internalComponent |
|
88 * @since App-frameworks6.1 |
|
89 */ |
|
90 NONSHARABLE_CLASS(CEditorCommandDeletePlainText) : public CEditorCommand |
|
91 { |
|
92 TEditorDeletePlainTextImpl iImpl; |
|
93 |
|
94 CEditorCommandDeletePlainText* |
|
95 CastToCEditorCommandDeletePlainText() { return this; } |
|
96 |
|
97 CEditorCommandDeletePlainText(MUnifiedEditor& aTarget, |
|
98 TInt aPos, TInt aLength) |
|
99 : iImpl(aTarget, aPos, aLength) {} |
|
100 public: |
|
101 static CEditorCommandDeletePlainText* NewL(TInt aPos, |
|
102 TInt aLength, MUnifiedEditor& aTarget) |
|
103 { |
|
104 return new(ELeave) CEditorCommandDeletePlainText(aTarget, aPos, aLength); |
|
105 } |
|
106 |
|
107 CCommand* CreateInverseL() const; |
|
108 |
|
109 TInt ExecuteL() const |
|
110 { |
|
111 return iImpl.ExecuteL(); |
|
112 } |
|
113 |
|
114 // This command can be coalesced with others of the same type |
|
115 TBool CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const |
|
116 { |
|
117 return iImpl.CanAdd(aPos, aLength, aTarget); |
|
118 } |
|
119 |
|
120 void Add(TInt aLength) |
|
121 { |
|
122 iImpl.Add(aLength); |
|
123 } |
|
124 }; |
|
125 |
|
126 /** |
|
127 * Command for inserting text in a specified style and format. |
|
128 * |
|
129 * @internalComponent |
|
130 * @since App-frameworks6.1 |
|
131 */ |
|
132 NONSHARABLE_CLASS(CEditorCommandInsertPlainText) : public CEditorCommand |
|
133 { |
|
134 TEditorInsertPlainTextImpl iImpl; |
|
135 |
|
136 CEditorCommandInsertPlainText* |
|
137 CastToCEditorCommandInsertPlainText() { return this; } |
|
138 CEditorCommandInsertPlainText(MUnifiedEditor& aTarget, TInt aPos, const TDesC& aText) |
|
139 : iImpl(aTarget, aPos, aText) {} |
|
140 public: |
|
141 static CEditorCommandInsertPlainText* NewL(TInt aPos, const TDesC& aText, |
|
142 MUnifiedEditor& aTarget) |
|
143 { |
|
144 return new(ELeave) CEditorCommandInsertPlainText(aTarget, aPos, aText); |
|
145 } |
|
146 /** |
|
147 * Gets the length specified, but this might entail the use of more than |
|
148 * one CCommand object. |
|
149 */ |
|
150 static CCommand* NewBatchL(TInt aPos, TInt aLength, MUnifiedEditor& aTarget); |
|
151 |
|
152 CCommand* CreateInverseL() const; |
|
153 |
|
154 TInt ExecuteL() const |
|
155 { |
|
156 return iImpl.ExecuteL(); |
|
157 } |
|
158 |
|
159 TBool CanAdd(TInt aPos, const TDesC& aText, MUnifiedEditor& aTarget) const |
|
160 { |
|
161 return iImpl.CanAdd(aPos, aText, aTarget); |
|
162 } |
|
163 |
|
164 void Add(TInt aPos, const TDesC& aText) |
|
165 { |
|
166 iImpl.Add(aPos, aText); |
|
167 } |
|
168 }; |
|
169 |
|
170 CCommand* CEditorCommandInsertPlainText::NewBatchL(TInt aPos, |
|
171 TInt aLength, MUnifiedEditor& aTarget) |
|
172 { |
|
173 CCommand* command = 0; |
|
174 TInt end = aPos + aLength; |
|
175 while (aLength) |
|
176 { |
|
177 TPtrC textSegment; |
|
178 aTarget.GetText(end - aLength, textSegment); |
|
179 TInt segLength = textSegment.Length(); |
|
180 if (aLength < segLength) |
|
181 segLength = aLength; |
|
182 if (KMaxCharsInSingleCommand < segLength) |
|
183 segLength = KMaxCharsInSingleCommand; |
|
184 CleanupStack::PushL(command); |
|
185 // coverity[double_free] |
|
186 command = CoalesceL(command, CEditorCommandInsertPlainText::NewL(aPos, |
|
187 textSegment.Left(segLength), aTarget)); |
|
188 CleanupStack::Pop(); |
|
189 aLength -= segLength; |
|
190 } |
|
191 return command; |
|
192 } |
|
193 |
|
194 CCommand* CEditorCommandInsertPlainText::CreateInverseL() const |
|
195 { |
|
196 return CEditorCommandDeletePlainText::NewL(iImpl.Pos(), iImpl.Text().Length(), |
|
197 iImpl.Target()); |
|
198 } |
|
199 |
|
200 |
|
201 CCommand* CEditorCommandDeletePlainText::CreateInverseL() const |
|
202 { |
|
203 return CEditorCommandInsertPlainText::NewBatchL(iImpl.Pos(), iImpl.Length(), |
|
204 iImpl.Target()); |
|
205 } |
|
206 |
|
207 ////////////////////////////////////////// |
|
208 // // |
|
209 // CEditorCommandInsertPlainTextProto // |
|
210 // // |
|
211 ////////////////////////////////////////// |
|
212 |
|
213 void CEditorCommandInsertPlainTextProto::Set(TInt aPos, const TDesC& aText) |
|
214 { |
|
215 iPos = aPos; |
|
216 iText = &aText; |
|
217 } |
|
218 |
|
219 UndoSystem::CCommand* CEditorCommandInsertPlainTextProto::CreateInverseL() const |
|
220 { |
|
221 return CEditorCommandDeletePlainText::NewL(iPos, iText->Length(), iTarget); |
|
222 } |
|
223 |
|
224 TInt CEditorCommandInsertPlainTextProto::ExecuteL() const |
|
225 { |
|
226 iTarget.InsertTextL(iPos, *iText); |
|
227 return KErrNone; |
|
228 } |
|
229 |
|
230 TBool CEditorCommandInsertPlainTextProto::PrepareToAddInverseToLastL( |
|
231 CSingleCommand& aLastCommand) const |
|
232 { |
|
233 if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid)) |
|
234 return EFalse; |
|
235 CEditorCommandDeletePlainText* last = |
|
236 static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeletePlainText(); |
|
237 if (!last) |
|
238 return EFalse; |
|
239 return last->CanAdd(iPos, iText->Length(), iTarget); |
|
240 } |
|
241 |
|
242 void CEditorCommandInsertPlainTextProto::AddInverseToLast(CSingleCommand& aLastCommand) const |
|
243 { |
|
244 ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid)); |
|
245 CEditorCommandDeletePlainText* last = |
|
246 static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandDeletePlainText(); |
|
247 ASSERT(last); |
|
248 last->Add(iText->Length()); |
|
249 } |
|
250 |
|
251 ////////////////////////////////////////// |
|
252 // // |
|
253 // CEditorCommandDeletePlainTextProto // |
|
254 // // |
|
255 ////////////////////////////////////////// |
|
256 |
|
257 void CEditorCommandDeletePlainTextProto::Set(TInt aPos, TInt aLength) |
|
258 { |
|
259 iPos = aPos; |
|
260 iLength = aLength; |
|
261 } |
|
262 |
|
263 CCommand* CEditorCommandDeletePlainTextProto::CreateInverseL() const |
|
264 { |
|
265 return CEditorCommandInsertPlainText::NewBatchL(iPos, iLength, iTarget); |
|
266 } |
|
267 |
|
268 TInt CEditorCommandDeletePlainTextProto::ExecuteL() const |
|
269 { |
|
270 iTarget.DeleteTextL(iPos, iLength); |
|
271 return KErrNone; |
|
272 } |
|
273 |
|
274 TBool CEditorCommandDeletePlainTextProto::PrepareToAddInverseToLastL( |
|
275 CSingleCommand& aLastCommand) const |
|
276 { |
|
277 if (iDeletedText.MaxLength() < iLength) |
|
278 return EFalse; |
|
279 if (aLastCommand.FamilyUid() != TUid::Uid(KUndoDllUid)) |
|
280 return EFalse; |
|
281 CEditorCommandInsertPlainText* last = |
|
282 static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandInsertPlainText(); |
|
283 if (!last) |
|
284 return EFalse; |
|
285 TBool result = EFalse; |
|
286 TPtrC textSegment; |
|
287 iTarget.GetText(iPos, textSegment); |
|
288 if (iLength <= textSegment.Length()) |
|
289 { |
|
290 result = last->CanAdd(iPos, textSegment.Left(iLength), iTarget); |
|
291 if (result) |
|
292 iDeletedText = textSegment.Left(iLength); |
|
293 } |
|
294 return result; |
|
295 } |
|
296 |
|
297 void CEditorCommandDeletePlainTextProto::AddInverseToLast(CSingleCommand& aLastCommand) const |
|
298 { |
|
299 ASSERT(aLastCommand.FamilyUid() == TUid::Uid(KUndoDllUid)); |
|
300 CEditorCommandInsertPlainText* last = |
|
301 static_cast<CEditorCommand&>(aLastCommand).CastToCEditorCommandInsertPlainText(); |
|
302 ASSERT(last); |
|
303 last->Add(iPos, iDeletedText); |
|
304 } |
|
305 |
|
306 ////////////////////////////////// |
|
307 // // |
|
308 // TEditorInsertPlainTextImpl // |
|
309 // // |
|
310 ////////////////////////////////// |
|
311 |
|
312 TInt TEditorInsertPlainTextImpl::ExecuteL(const TDesC* aStyle, |
|
313 const TTmCharFormatLayer* aChar, |
|
314 const RTmParFormatLayer* aPar) const |
|
315 { |
|
316 iTarget.InsertTextL(iPos, iText, aStyle, aChar, aPar); |
|
317 return KErrNone; |
|
318 } |
|
319 |
|
320 TInt TEditorInsertPlainTextImpl::ExecuteL() const |
|
321 { |
|
322 return ExecuteL(0, 0, 0); |
|
323 } |
|
324 |
|
325 TInt TEditorInsertPlainTextImpl::CanAdd(TInt aPos, const TDesC& aText, MUnifiedEditor& aTarget) const |
|
326 { |
|
327 if (&aTarget != &iTarget) |
|
328 return EFalse; |
|
329 TInt length = aText.Length(); |
|
330 if (KMaxCharsInSingleCommand <= iText.Length() + length) |
|
331 return EFalse; |
|
332 return aPos <= iPos && iPos <= aPos + length; |
|
333 } |
|
334 |
|
335 void TEditorInsertPlainTextImpl::Add(TInt aPos, const TDesC& aText) |
|
336 { |
|
337 TPtrC left = aText.Left(iPos - aPos); |
|
338 TPtrC right = aText.Mid(iPos - aPos); |
|
339 iText.Insert(0, left); |
|
340 iText.Append(right); |
|
341 iPos = aPos; |
|
342 } |
|
343 |
|
344 ////////////////////////////////// |
|
345 // // |
|
346 // TEditorDeletePlainTextImpl // |
|
347 // // |
|
348 ////////////////////////////////// |
|
349 |
|
350 TInt TEditorDeletePlainTextImpl::ExecuteL() const |
|
351 { |
|
352 iTarget.DeleteTextL(iPos, iLength); |
|
353 return KErrNone; |
|
354 } |
|
355 |
|
356 TBool TEditorDeletePlainTextImpl::CanAdd(TInt aPos, TInt aLength, MUnifiedEditor& aTarget) const |
|
357 { |
|
358 return &aTarget == &iTarget && iPos <= aPos && aPos <= iLength + iPos |
|
359 && aLength + iLength <= KMaxCharsInSingleCommand; |
|
360 } |
|
361 |
|
362 void TEditorDeletePlainTextImpl::Add(TInt aLength) |
|
363 { |
|
364 iLength += aLength; |
|
365 } |
|
366 |
|
367 ///////////////////////////// |
|
368 // // |
|
369 // TEditorPasteProtoImpl // |
|
370 // // |
|
371 ///////////////////////////// |
|
372 |
|
373 void TEditorPasteProtoImpl::Set(const CStreamStore& aStore, |
|
374 const CStreamDictionary& aDict, |
|
375 TInt aPos) |
|
376 { |
|
377 iStore = &aStore; |
|
378 iStreamDictionary = &aDict; |
|
379 iPos = aPos; |
|
380 } |
|
381 |
|
382 void TEditorPasteProtoImpl::OpenPlainTextStreamLC(RStoreReadStream& aStream) const |
|
383 { |
|
384 TStreamId plainTextStream = iStreamDictionary->At(KClipboardUidTypePlainText); |
|
385 if (plainTextStream == KNullStreamId) |
|
386 User::Leave(KErrNotSupported); // don't know how to undo this |
|
387 aStream.OpenLC(*iStore, plainTextStream); |
|
388 } |
|
389 |
|
390 TInt TEditorPasteProtoImpl::LengthL() const |
|
391 { |
|
392 RStoreReadStream stream; |
|
393 OpenPlainTextStreamLC(stream); |
|
394 TInt length = stream.ReadInt32L(); |
|
395 CleanupStack::PopAndDestroy(); |
|
396 return length; |
|
397 } |
|
398 |
|
399 TInt TEditorPasteProtoImpl::ExecuteL() const |
|
400 { |
|
401 MUnifiedEditor::MClipboardSupport* ci = iTarget.ClipboardSupport(); |
|
402 ASSERT(ci); |
|
403 ci->PasteFromStoreL(*iStore, *iStreamDictionary, iPos); |
|
404 return KErrNone; |
|
405 } |
|
406 |
|
407 ///////////////////////////////////////// |
|
408 // // |
|
409 // CEditorCommandPastePlainTextProto // |
|
410 // // |
|
411 ///////////////////////////////////////// |
|
412 |
|
413 void CEditorCommandPastePlainTextProto::Set(const CStreamStore& aStore, |
|
414 const CStreamDictionary& aStreamDictionary, |
|
415 TInt aPos) |
|
416 { |
|
417 iImpl.Set(aStore, aStreamDictionary, aPos); |
|
418 } |
|
419 |
|
420 UndoSystem::CCommand* CEditorCommandPastePlainTextProto::CreateInverseL() const |
|
421 { |
|
422 return CEditorCommandDeletePlainText::NewL(iImpl.Pos(), iImpl.LengthL(), iImpl.Target()); |
|
423 } |
|
424 |
|
425 TInt CEditorCommandPastePlainTextProto::ExecuteL() const |
|
426 { |
|
427 return iImpl.ExecuteL(); |
|
428 } |