|
1 // text_formatter.cpp |
|
2 // |
|
3 // Copyright (c) 2006 - 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "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 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <e32base.h> |
|
14 #include "ioutils.h" |
|
15 #include "pod_lexer.h" |
|
16 #include "pod_formatter.h" |
|
17 |
|
18 using namespace IoUtils; |
|
19 |
|
20 |
|
21 // |
|
22 // Constants. |
|
23 // |
|
24 |
|
25 _LIT(KSpace, " "); |
|
26 _LIT(KNewLine, "\r\n"); |
|
27 |
|
28 |
|
29 // |
|
30 // CTextBuffer. |
|
31 // |
|
32 |
|
33 EXPORT_C CTextBuffer* CTextBuffer::NewL(TInt aExpandSize) |
|
34 { |
|
35 CTextBuffer* self = CTextBuffer::NewLC(aExpandSize); |
|
36 CleanupStack::Pop(self); |
|
37 return self; |
|
38 } |
|
39 |
|
40 EXPORT_C CTextBuffer* CTextBuffer::NewLC(TInt aExpandSize) |
|
41 { |
|
42 CTextBuffer* self = new(ELeave) CTextBuffer(); |
|
43 CleanupStack::PushL(self); |
|
44 self->ConstructL(aExpandSize); |
|
45 return self; |
|
46 } |
|
47 |
|
48 EXPORT_C CTextBuffer::~CTextBuffer() |
|
49 { |
|
50 Cancel(); |
|
51 delete iBuf; |
|
52 delete iScratchBuf; |
|
53 delete iScratchBuf8; |
|
54 iAttributes.Close(); |
|
55 } |
|
56 |
|
57 EXPORT_C void CTextBuffer::Zero() |
|
58 { |
|
59 iBuf->Delete(0, iBuf->Size()); |
|
60 iAttributes.Reset(); |
|
61 } |
|
62 |
|
63 EXPORT_C void CTextBuffer::Reset() |
|
64 { |
|
65 iBuf->Reset(); |
|
66 iAttributes.Reset(); |
|
67 } |
|
68 |
|
69 EXPORT_C void CTextBuffer::ResetText() |
|
70 { |
|
71 iBuf->Reset(); |
|
72 } |
|
73 |
|
74 EXPORT_C void CTextBuffer::SetAttributesL(TUint aAttributes, ConsoleAttributes::TColor aForegroundColor, ConsoleAttributes::TColor aBackgroundColor) |
|
75 { |
|
76 const TInt numAttributes = iAttributes.Count(); |
|
77 if (numAttributes == 0) |
|
78 { |
|
79 if (Length() == 0) |
|
80 { |
|
81 TAttributes attributes(0, aAttributes, aForegroundColor, aBackgroundColor); |
|
82 iAttributes.AppendL(attributes); |
|
83 } |
|
84 else |
|
85 { |
|
86 TAttributes attributes(Length(), aAttributes, aForegroundColor, aBackgroundColor); |
|
87 if (!attributes.Matches(ConsoleAttributes::ENone, ConsoleAttributes::EUnchanged, ConsoleAttributes::EUnchanged)) |
|
88 { |
|
89 TAttributes defaultAttributes(0, ConsoleAttributes::ENone, ConsoleAttributes::EUnchanged, ConsoleAttributes::EUnchanged); |
|
90 iAttributes.AppendL(defaultAttributes); |
|
91 TInt err = iAttributes.Append(attributes); |
|
92 if (err != KErrNone) |
|
93 { |
|
94 iAttributes.Reset(); |
|
95 User::Leave(err); |
|
96 } |
|
97 } |
|
98 } |
|
99 } |
|
100 else if (iAttributes[numAttributes - 1].Matches(aAttributes, aForegroundColor, aBackgroundColor)) |
|
101 { |
|
102 // Do nothing. |
|
103 } |
|
104 else if (iAttributes[numAttributes - 1].iPosition == Length()) |
|
105 { |
|
106 TAttributes& att = iAttributes[numAttributes - 1]; |
|
107 if (aAttributes & ConsoleAttributes::ENone) |
|
108 { |
|
109 att.iAttributes.iAttributes = aAttributes; |
|
110 att.iAttributes.iForegroundColor = aForegroundColor; |
|
111 att.iAttributes.iBackgroundColor = aBackgroundColor; |
|
112 } |
|
113 else |
|
114 { |
|
115 // Merge on top of existing attributes |
|
116 att.iAttributes.iAttributes |= aAttributes; |
|
117 if (aForegroundColor != ConsoleAttributes::EUnchanged) att.iAttributes.iForegroundColor = aForegroundColor; |
|
118 if (aBackgroundColor != ConsoleAttributes::EUnchanged) att.iAttributes.iBackgroundColor = aBackgroundColor; |
|
119 } |
|
120 } |
|
121 else |
|
122 { |
|
123 TAttributes attributes(Length(), aAttributes, aForegroundColor, aBackgroundColor); |
|
124 iAttributes.AppendL(attributes); |
|
125 } |
|
126 } |
|
127 |
|
128 EXPORT_C void CTextBuffer::SetAttributesL(const ConsoleAttributes::TAttributes& aAttributes) |
|
129 { |
|
130 SetAttributesL(aAttributes.iAttributes, aAttributes.iForegroundColor, aAttributes.iBackgroundColor); |
|
131 } |
|
132 |
|
133 EXPORT_C void CTextBuffer::GetCurrentAttributes(TUint& aAttributes, ConsoleAttributes::TColor& aForegroundColor, ConsoleAttributes::TColor& aBackgroundColor) const |
|
134 { |
|
135 if (iAttributes.Count() > 0) |
|
136 { |
|
137 const TAttributes& att = iAttributes[iAttributes.Count() - 1]; |
|
138 aAttributes = att.iAttributes.iAttributes; |
|
139 aForegroundColor = att.iAttributes.iForegroundColor; |
|
140 aBackgroundColor = att.iAttributes.iBackgroundColor; |
|
141 } |
|
142 else |
|
143 { |
|
144 aAttributes = ConsoleAttributes::ENone; |
|
145 aForegroundColor = ConsoleAttributes::EUnchanged; |
|
146 aBackgroundColor = ConsoleAttributes::EUnchanged; |
|
147 } |
|
148 } |
|
149 |
|
150 EXPORT_C void CTextBuffer::GetAttributes(TInt aPos, TUint& aAttributes, ConsoleAttributes::TColor& aForegroundColor, ConsoleAttributes::TColor& aBackgroundColor) const |
|
151 { |
|
152 ASSERT(aPos < Length()); |
|
153 |
|
154 aAttributes = ConsoleAttributes::ENone; |
|
155 aForegroundColor = ConsoleAttributes::EUnchanged; |
|
156 aBackgroundColor = ConsoleAttributes::EUnchanged; |
|
157 |
|
158 const TInt numAttributes = iAttributes.Count(); |
|
159 for (TInt i = 0; i < numAttributes; ++i) |
|
160 { |
|
161 const TAttributes& att = iAttributes[i]; |
|
162 if (aPos < att.iPosition) |
|
163 { |
|
164 return; |
|
165 } |
|
166 else |
|
167 { |
|
168 aAttributes = att.iAttributes.iAttributes; |
|
169 aForegroundColor = att.iAttributes.iForegroundColor; |
|
170 aBackgroundColor = att.iAttributes.iBackgroundColor; |
|
171 } |
|
172 } |
|
173 } |
|
174 |
|
175 EXPORT_C void CTextBuffer::AppendL(const TChar& aChar) |
|
176 { |
|
177 TUint16 ch = (TUint16)TUint(aChar); // We don't support surrogate pairs |
|
178 iBuf->InsertL(iBuf->Size(), &ch, 2); |
|
179 } |
|
180 |
|
181 EXPORT_C void CTextBuffer::AppendL(const TDesC& aText) |
|
182 { |
|
183 iBuf->InsertL(iBuf->Size(), aText.Ptr(), aText.Size()); |
|
184 } |
|
185 |
|
186 EXPORT_C void CTextBuffer::AppendL(const TDesC8& aText) |
|
187 { |
|
188 if (!iScratchBuf) |
|
189 { |
|
190 iScratchBuf = HBufC::NewL(Max(aText.Length(), 256)); |
|
191 } |
|
192 if (iScratchBuf->Des().MaxLength() < aText.Length()) |
|
193 { |
|
194 iScratchBuf = iScratchBuf->ReAllocL(Max(iScratchBuf->Des().MaxLength()*2, aText.Length())); |
|
195 } |
|
196 iScratchBuf->Des().Copy(aText); |
|
197 iBuf->InsertL(iBuf->Size(), iScratchBuf->Ptr(), iScratchBuf->Size()); |
|
198 } |
|
199 |
|
200 EXPORT_C void CTextBuffer::AppendL(const CTextBuffer& aText) |
|
201 { |
|
202 AppendL(aText, 0, aText.Length()); |
|
203 } |
|
204 |
|
205 EXPORT_C void CTextBuffer::AppendL(const CTextBuffer& aText, TInt aPosition) |
|
206 { |
|
207 AppendL(aText, aPosition, aText.Length() - aPosition); |
|
208 } |
|
209 |
|
210 EXPORT_C void CTextBuffer::AppendL(const CTextBuffer& aText, TInt aPosition, TInt aLength) |
|
211 { |
|
212 const TInt numAttributes = aText.iAttributes.Count(); |
|
213 if (numAttributes > 0) |
|
214 { |
|
215 TInt textPos = 0; |
|
216 TInt appendCount = 0; |
|
217 TInt blockIndex = 0; |
|
218 const TDesC* block = NULL; |
|
219 do |
|
220 { |
|
221 TUint attributes; |
|
222 ConsoleAttributes::TColor foregroundColor; |
|
223 ConsoleAttributes::TColor backgroundColor; |
|
224 aText.NextBlock(blockIndex, block, attributes, foregroundColor, backgroundColor); |
|
225 if (block != NULL) |
|
226 { |
|
227 if ((textPos + block->Length()) > aPosition) |
|
228 { |
|
229 SetAttributesL(attributes, foregroundColor, backgroundColor); |
|
230 TInt blockOffset = aPosition - textPos; |
|
231 if (blockOffset < 0) |
|
232 { |
|
233 blockOffset = 0; |
|
234 } |
|
235 TPtrC appendBlock(block->Mid(blockOffset, Min(aLength - appendCount, block->Length() - blockOffset))); |
|
236 AppendL(appendBlock); |
|
237 appendCount += appendBlock.Length(); |
|
238 if (appendCount == aLength) |
|
239 { |
|
240 break; |
|
241 } |
|
242 } |
|
243 textPos += block->Length(); |
|
244 } |
|
245 } |
|
246 while (block != NULL); |
|
247 } |
|
248 else |
|
249 { |
|
250 AppendL(aText.Descriptor().Mid(aPosition, aLength)); |
|
251 } |
|
252 } |
|
253 |
|
254 EXPORT_C void CTextBuffer::AppendFormatL(TRefByValue<const TDesC> aFmt, ...) |
|
255 { |
|
256 VA_LIST list; |
|
257 VA_START(list, aFmt); |
|
258 AppendFormatListL(aFmt, list); |
|
259 } |
|
260 |
|
261 EXPORT_C void CTextBuffer::AppendFormatListL(const TDesC16& aFmt, VA_LIST& aList) |
|
262 { |
|
263 TOverflowLeave overflow; |
|
264 TInt err = KErrNone; |
|
265 do |
|
266 { |
|
267 TPtr ptr(iScratchBuf->Des()); |
|
268 ptr.Zero(); |
|
269 TRAP(err, ptr.AppendFormatList(aFmt, aList, &overflow)); |
|
270 if (err == KErrOverflow) |
|
271 { |
|
272 iScratchBuf = iScratchBuf->ReAllocL(ptr.MaxLength() * 2); |
|
273 } |
|
274 } |
|
275 while (err == KErrOverflow); |
|
276 |
|
277 User::LeaveIfError(err); |
|
278 iBuf->InsertL(iBuf->Size(), iScratchBuf->Ptr(), iScratchBuf->Size()); |
|
279 } |
|
280 |
|
281 EXPORT_C void CTextBuffer::AppendFormatL(TRefByValue<const TDesC8> aFmt, ...) |
|
282 { |
|
283 VA_LIST list; |
|
284 VA_START(list, aFmt); |
|
285 AppendFormatListL(aFmt, list); |
|
286 } |
|
287 |
|
288 EXPORT_C void CTextBuffer::AppendFormatListL(const TDesC8& aFmt, VA_LIST& aList) |
|
289 { |
|
290 TOverflowLeave8 overflow; |
|
291 TInt err = KErrNone; |
|
292 if (!iScratchBuf8) |
|
293 { |
|
294 iScratchBuf8 = HBufC8::NewL(0x100); |
|
295 } |
|
296 |
|
297 do |
|
298 { |
|
299 TPtr8 ptr(iScratchBuf8->Des()); |
|
300 ptr.Zero(); |
|
301 TRAP(err, ptr.AppendFormatList(aFmt, aList, &overflow)); |
|
302 if (err == KErrOverflow) |
|
303 { |
|
304 iScratchBuf8 = iScratchBuf8->ReAllocL(ptr.MaxLength() * 2); |
|
305 } |
|
306 } |
|
307 while (err == KErrOverflow); |
|
308 |
|
309 User::LeaveIfError(err); |
|
310 |
|
311 TPtr8 ptr(iScratchBuf8->Des()); |
|
312 if (iScratchBuf->Des().MaxLength() < ptr.Length()) |
|
313 { |
|
314 iScratchBuf = iScratchBuf->ReAllocL(Max(iScratchBuf->Des().MaxLength()*2, ptr.Length())); |
|
315 } |
|
316 iScratchBuf->Des().Copy(*iScratchBuf8); |
|
317 |
|
318 iBuf->InsertL(iBuf->Size(), iScratchBuf->Ptr(), iScratchBuf->Size()); |
|
319 } |
|
320 |
|
321 EXPORT_C void CTextBuffer::AppendHumanReadableSizeL(TInt aSize) |
|
322 { |
|
323 AppendHumanReadableSizeL(TInt64(aSize), EColumnAlignedRight); |
|
324 } |
|
325 |
|
326 EXPORT_C void CTextBuffer::AppendHumanReadableSizeL(TInt64 aSize) |
|
327 { |
|
328 AppendHumanReadableSizeL(aSize, EColumnAlignedRight); |
|
329 } |
|
330 |
|
331 EXPORT_C void CTextBuffer::AppendHumanReadableSizeL(TInt aSize, TAlignment aAlignment) |
|
332 { |
|
333 AppendHumanReadableSizeL(TInt64(aSize), aAlignment); |
|
334 } |
|
335 |
|
336 EXPORT_C void CTextBuffer::AppendHumanReadableSizeL(TInt64 aSize, TAlignment aAlignment) |
|
337 { |
|
338 const TInt64 KB = 1024; |
|
339 const TInt64 MB = KB * KB; |
|
340 const TInt64 GB = MB * KB; |
|
341 const TInt64 TB = GB * KB; |
|
342 _LIT(KBytes, " B "); |
|
343 _LIT(KKilobytes, " KB"); |
|
344 _LIT(KMegabytes, " MB"); |
|
345 _LIT(KGigabytes, " GB"); |
|
346 _LIT(KTerabytes, " TB"); |
|
347 |
|
348 _LIT(KLeftWhole, "%- 7.0f"); |
|
349 _LIT(KLeftFrac, "%- 7.2f"); |
|
350 _LIT(KRightWhole, "%+ 7.0f"); |
|
351 _LIT(KRightFrac, "%+ 7.2f"); |
|
352 _LIT(KNormalWhole, "%.0f"); |
|
353 _LIT(KNormalFrac, "%.2f"); |
|
354 |
|
355 const TDesC* suff = &KBytes; |
|
356 TReal n = aSize; |
|
357 TInt64 factor = 1; |
|
358 |
|
359 TInt64 absSize = aSize; |
|
360 if (absSize < 0) absSize = -absSize; |
|
361 |
|
362 if (absSize >= TB) |
|
363 { |
|
364 suff = &KTerabytes; |
|
365 factor = TB; |
|
366 } |
|
367 else if (absSize >= GB) |
|
368 { |
|
369 suff = &KGigabytes; |
|
370 factor = GB; |
|
371 } |
|
372 else if (absSize >= MB) |
|
373 { |
|
374 suff = &KMegabytes; |
|
375 factor = MB; |
|
376 } |
|
377 else if (absSize >= KB) |
|
378 { |
|
379 suff = &KKilobytes; |
|
380 factor = KB; |
|
381 } |
|
382 |
|
383 n = n / (TReal)factor; |
|
384 TBool wholeNumUnits = (absSize & (factor-1)) == 0; // ie aSize % factor == 0 |
|
385 |
|
386 const TDesC* fmt = NULL; |
|
387 if (aAlignment == EColumnAlignedLeft) |
|
388 { |
|
389 fmt = wholeNumUnits ? &KLeftWhole : &KLeftFrac; |
|
390 } |
|
391 else if (aAlignment == EColumnAlignedRight) |
|
392 { |
|
393 fmt = wholeNumUnits ? &KRightWhole : &KRightFrac; |
|
394 } |
|
395 else |
|
396 { |
|
397 fmt = wholeNumUnits ? &KNormalWhole : &KNormalFrac; |
|
398 } |
|
399 |
|
400 AppendFormatL(*fmt, n); |
|
401 AppendL(*suff); |
|
402 } |
|
403 |
|
404 EXPORT_C void CTextBuffer::AppendSpacesL(TInt aCount) |
|
405 { |
|
406 ASSERT(aCount >= 0); |
|
407 while (aCount > 0) |
|
408 { |
|
409 AppendL(KSpace); |
|
410 --aCount; |
|
411 } |
|
412 } |
|
413 |
|
414 EXPORT_C void CTextBuffer::Delete(TInt aPos, TInt aLength) |
|
415 { |
|
416 //for (TInt i = 0; i < iAttributes.Count(); i++) |
|
417 // { |
|
418 // RDebug::Printf("attribute %d: pos %d", i, iAttributes[i].iPosition); |
|
419 // } |
|
420 |
|
421 // Find the first and last attributes that are inside the delete region. |
|
422 TInt firstAttribute = -1; |
|
423 TInt lastAttribute = -1; |
|
424 TInt numAttributes = iAttributes.Count(); |
|
425 for (TInt i = (numAttributes - 1); i >= 0; --i) |
|
426 { |
|
427 const TAttributes& thisAttribute = iAttributes[i]; |
|
428 if ((lastAttribute == -1) && (thisAttribute.iPosition >= aPos) && (thisAttribute.iPosition < aPos + aLength)) |
|
429 { |
|
430 lastAttribute = i; |
|
431 } |
|
432 if (lastAttribute >= 0 && thisAttribute.iPosition >= aPos) |
|
433 { |
|
434 firstAttribute = i; |
|
435 } |
|
436 } |
|
437 //RDebug::Printf("firstAttribute=%d lastAttribute=%d", firstAttribute, lastAttribute); |
|
438 |
|
439 if ((lastAttribute > 0)) |
|
440 { |
|
441 // Set the position of the last affected attribute to just after the deleted chunk. |
|
442 iAttributes[lastAttribute].iPosition = aPos + aLength; |
|
443 |
|
444 // Remove all but the last affected attribute. Need to keep the last affected attribute |
|
445 // because it has an impact on the formatting of text that appears after the deleted chunk. |
|
446 for (TInt i = (lastAttribute - 1); i >= firstAttribute; --i) |
|
447 { |
|
448 iAttributes.Remove(i); |
|
449 } |
|
450 } |
|
451 |
|
452 // Update the positions of attributes after the block being deleted. |
|
453 numAttributes = iAttributes.Count(); |
|
454 for (TInt i = Max(0, firstAttribute); i < numAttributes; ++i) |
|
455 { |
|
456 TAttributes& thisAttribute = iAttributes[i]; |
|
457 if (thisAttribute.iPosition >= aPos + aLength) |
|
458 { |
|
459 thisAttribute.iPosition -= aLength; |
|
460 } |
|
461 } |
|
462 iBuf->Delete(aPos * 2, aLength * 2); |
|
463 } |
|
464 |
|
465 EXPORT_C TInt CTextBuffer::Length() const |
|
466 { |
|
467 return iBuf->Size() / 2; |
|
468 } |
|
469 |
|
470 EXPORT_C const TDesC& CTextBuffer::Descriptor() const |
|
471 { |
|
472 TPtr8 narrowPtr(iBuf->Ptr(0)); |
|
473 iPtr.Set((const TUint16 *)narrowPtr.Ptr(), narrowPtr.Length() / 2); |
|
474 return iPtr; |
|
475 } |
|
476 |
|
477 EXPORT_C const TDesC& CTextBuffer::Descriptor(TInt aPos, TInt aLength) const |
|
478 { |
|
479 TPtr8 narrowPtr(iBuf->Ptr(aPos * 2)); |
|
480 iPtr.Set((const TUint16 *)narrowPtr.Ptr(), aLength); |
|
481 return iPtr; |
|
482 } |
|
483 |
|
484 EXPORT_C TPtrC8 CTextBuffer::Collapse() |
|
485 { |
|
486 TPtr8 narrowPtr(iBuf->Ptr(0)); |
|
487 TPtr ptr((TUint16 *)narrowPtr.Ptr(), narrowPtr.Length() / 2, narrowPtr.Length() / 2); |
|
488 return ptr.Collapse(); |
|
489 } |
|
490 |
|
491 EXPORT_C TInt CTextBuffer::Write(RIoWriteHandle& aWriteHandle) const |
|
492 { |
|
493 return Write(aWriteHandle, 0, Length()); |
|
494 } |
|
495 |
|
496 EXPORT_C void CTextBuffer::Write(RIoWriteHandle& aWriteHandle, TRequestStatus& aStatus) const |
|
497 { |
|
498 Write(aWriteHandle, 0, Length(), aStatus); |
|
499 } |
|
500 |
|
501 EXPORT_C TInt CTextBuffer::Write(RIoWriteHandle& aWriteHandle, TInt aPosition, TInt aLength) const |
|
502 { |
|
503 const TInt numAttributes = iAttributes.Count(); |
|
504 if ((aWriteHandle.AttachedToConsole() > 0) && (numAttributes > 0)) |
|
505 { |
|
506 // Write the text buffer to the console a block at a time, updating the console's attributes at the beginning of each block. |
|
507 TInt blockIndex = 0; |
|
508 TInt textPos = 0; |
|
509 TInt writeCount = 0; |
|
510 const TDesC* block = NULL; |
|
511 do |
|
512 { |
|
513 TUint attributes; |
|
514 ConsoleAttributes::TColor foregroundColor; |
|
515 ConsoleAttributes::TColor backgroundColor; |
|
516 NextBlock(blockIndex, block, attributes, foregroundColor, backgroundColor); |
|
517 if (block != NULL) |
|
518 { |
|
519 if ((textPos + block->Length()) > aPosition) |
|
520 { |
|
521 RIoConsoleWriteHandle(aWriteHandle).SetAttributes(attributes, foregroundColor, backgroundColor); // Ignore error - may not be supported. |
|
522 TInt blockOffset = aPosition - textPos; |
|
523 if (blockOffset < 0) |
|
524 { |
|
525 blockOffset = 0; |
|
526 } |
|
527 TPtrC toWrite(block->Mid(blockOffset, Min(aLength - writeCount, block->Length() - blockOffset))); |
|
528 TInt err = aWriteHandle.Write(toWrite); |
|
529 if (err) |
|
530 { |
|
531 return err; |
|
532 } |
|
533 writeCount += toWrite.Length(); |
|
534 if (writeCount == aLength) |
|
535 { |
|
536 break; |
|
537 } |
|
538 } |
|
539 textPos += block->Length(); |
|
540 } |
|
541 } |
|
542 while (block != NULL); |
|
543 } |
|
544 else |
|
545 { |
|
546 return aWriteHandle.Write(Descriptor().Mid(aPosition, aLength)); |
|
547 } |
|
548 |
|
549 return KErrNone; |
|
550 } |
|
551 |
|
552 EXPORT_C void CTextBuffer::Write(RIoWriteHandle& aWriteHandle, TInt aPosition, TInt aLength, TRequestStatus& aStatus) const |
|
553 { |
|
554 const TInt numAttributes = iAttributes.Count(); |
|
555 if ((aWriteHandle.AttachedToConsole() > 0) && (numAttributes > 0)) |
|
556 { |
|
557 // Write the text buffer asynchronously to the console a block at a time, updating the console's attributes at the beginning of each block. |
|
558 if (!IsAdded()) |
|
559 { |
|
560 CActiveScheduler::Add(const_cast<CTextBuffer*>(this)); |
|
561 } |
|
562 aStatus = KRequestPending; |
|
563 iWriteStatus = &aStatus; |
|
564 iAsyncBlockIndex = 0; |
|
565 iAsyncWritePos = 0; |
|
566 iAsyncWriteStartPos = aPosition; |
|
567 iAsyncWriteLength = aLength; |
|
568 iConsoleWriteHandle = aWriteHandle; |
|
569 AsyncWriteNextBlock(); |
|
570 } |
|
571 else |
|
572 { |
|
573 aWriteHandle.Write(Descriptor().Mid(aPosition, aLength), aStatus); |
|
574 } |
|
575 } |
|
576 |
|
577 CTextBuffer::CTextBuffer() |
|
578 : CActive(CActive::EPriorityStandard), iPtr(NULL, 0) |
|
579 { |
|
580 } |
|
581 |
|
582 void CTextBuffer::ConstructL(TInt aExpandSize) |
|
583 { |
|
584 iBuf = CBufFlat::NewL(aExpandSize); |
|
585 iScratchBuf = HBufC::NewL(aExpandSize); |
|
586 } |
|
587 |
|
588 void CTextBuffer::NextBlock(TInt& aBlockIndex, const TDesC*& aText, TUint& aAttributes, ConsoleAttributes::TColor& aForegroundColor, ConsoleAttributes::TColor& aBackgroundColor) const |
|
589 { |
|
590 if (iAttributes.Count() > 0) |
|
591 { |
|
592 if (aBlockIndex < iAttributes.Count()) |
|
593 { |
|
594 const TAttributes& thisAttribute = iAttributes[aBlockIndex]; |
|
595 aAttributes = thisAttribute.iAttributes.iAttributes; |
|
596 aForegroundColor = thisAttribute.iAttributes.iForegroundColor; |
|
597 aBackgroundColor = thisAttribute.iAttributes.iBackgroundColor; |
|
598 TInt length; |
|
599 if (aBlockIndex < (iAttributes.Count() - 1)) |
|
600 { |
|
601 length = iAttributes[aBlockIndex + 1].iPosition - thisAttribute.iPosition; |
|
602 } |
|
603 else |
|
604 { |
|
605 length = Length() - thisAttribute.iPosition; |
|
606 } |
|
607 aText = &Descriptor(thisAttribute.iPosition, length); |
|
608 ++aBlockIndex; |
|
609 } |
|
610 else |
|
611 { |
|
612 aText = NULL; |
|
613 } |
|
614 } |
|
615 else |
|
616 { |
|
617 // There are no attributes, so block zero is the whole buffer. |
|
618 ASSERT((aBlockIndex == 0) || (aBlockIndex == 1)); |
|
619 if (aBlockIndex == 0) |
|
620 { |
|
621 aAttributes = ConsoleAttributes::ENone; |
|
622 aForegroundColor = ConsoleAttributes::EUnchanged; |
|
623 aBackgroundColor = ConsoleAttributes::EUnchanged; |
|
624 aText = &Descriptor(0, Length()); |
|
625 ++aBlockIndex; |
|
626 } |
|
627 else |
|
628 { |
|
629 aText = NULL; |
|
630 } |
|
631 } |
|
632 } |
|
633 |
|
634 void CTextBuffer::AsyncWriteNextBlock() const |
|
635 { |
|
636 const TDesC* block = NULL; |
|
637 TUint attributes; |
|
638 ConsoleAttributes::TColor foregroundColor; |
|
639 ConsoleAttributes::TColor backgroundColor; |
|
640 NextBlock(iAsyncBlockIndex, block, attributes, foregroundColor, backgroundColor); |
|
641 if (block != NULL) |
|
642 { |
|
643 if ((iAsyncWritePos + block->Length()) > iAsyncWriteStartPos) |
|
644 { |
|
645 iConsoleWriteHandle.SetAttributes(attributes, foregroundColor, backgroundColor); // Ignore error - may not be supported. |
|
646 TInt blockOffset = iAsyncWriteStartPos - iAsyncWritePos; |
|
647 if (blockOffset < 0) |
|
648 { |
|
649 blockOffset = 0; |
|
650 } |
|
651 iAsyncWritePtr.Set(block->Mid(blockOffset, Min(iAsyncWriteLength, block->Length() - blockOffset))); |
|
652 iAsyncWriteLength -= iAsyncWritePtr.Length(); |
|
653 iConsoleWriteHandle.Write(iAsyncWritePtr, const_cast<TRequestStatus&>(iStatus)); |
|
654 const_cast<CTextBuffer*>(this)->SetActive(); |
|
655 } |
|
656 iAsyncWritePos += block->Length(); |
|
657 } |
|
658 else |
|
659 { |
|
660 User::RequestComplete(iWriteStatus, KErrNone); |
|
661 } |
|
662 } |
|
663 |
|
664 void CTextBuffer::RunL() |
|
665 { |
|
666 if (iStatus.Int() || (iAsyncWriteLength <= 0)) |
|
667 { |
|
668 User::RequestComplete(iWriteStatus, iStatus.Int()); |
|
669 } |
|
670 else |
|
671 { |
|
672 AsyncWriteNextBlock(); |
|
673 } |
|
674 } |
|
675 |
|
676 void CTextBuffer::DoCancel() |
|
677 { |
|
678 iConsoleWriteHandle.WriteCancel(); |
|
679 } |
|
680 |
|
681 CTextBuffer::TAttributes::TAttributes(TInt aPosition, TUint aAttributes, ConsoleAttributes::TColor aForegroundColor, ConsoleAttributes::TColor aBackgroundColor) |
|
682 : iPosition(aPosition), iAttributes(aAttributes, aForegroundColor, aBackgroundColor) |
|
683 { |
|
684 } |
|
685 |
|
686 TBool CTextBuffer::TAttributes::Matches(TUint aAttributes, ConsoleAttributes::TColor aForegroundColor, ConsoleAttributes::TColor aBackgroundColor) const |
|
687 { |
|
688 return ((aAttributes == iAttributes.iAttributes) && (aForegroundColor == iAttributes.iForegroundColor) && (aBackgroundColor == iAttributes.iBackgroundColor)); |
|
689 } |
|
690 |
|
691 |
|
692 // |
|
693 // CTextFormatter. |
|
694 // |
|
695 |
|
696 EXPORT_C CTextFormatter* CTextFormatter::NewL(TInt aAvailableWidth) |
|
697 { |
|
698 CTextFormatter* self = CTextFormatter::NewLC(aAvailableWidth); |
|
699 CleanupStack::Pop(self); |
|
700 return self; |
|
701 } |
|
702 |
|
703 EXPORT_C CTextFormatter* CTextFormatter::NewLC(TInt aAvailableWidth) |
|
704 { |
|
705 CTextFormatter* self = new(ELeave) CTextFormatter(aAvailableWidth); |
|
706 CleanupStack::PushL(self); |
|
707 self->ConstructL(); |
|
708 return self; |
|
709 } |
|
710 |
|
711 EXPORT_C CTextFormatter* CTextFormatter::NewL(RIoConsoleWriteHandle& aConsoleWriteHandle) |
|
712 { |
|
713 CTextFormatter* self = CTextFormatter::NewLC(aConsoleWriteHandle); |
|
714 CleanupStack::Pop(self); |
|
715 return self; |
|
716 } |
|
717 |
|
718 EXPORT_C CTextFormatter* CTextFormatter::NewLC(RIoConsoleWriteHandle& aConsoleWriteHandle) |
|
719 { |
|
720 TSize size; |
|
721 if (aConsoleWriteHandle.AttachedToConsole()) |
|
722 { |
|
723 User::LeaveIfError(aConsoleWriteHandle.GetScreenSize(size)); |
|
724 } |
|
725 else |
|
726 { |
|
727 size.iWidth = 80; |
|
728 } |
|
729 CTextFormatter* self = CTextFormatter::NewLC(size.iWidth); |
|
730 self->iWriteHandle = &aConsoleWriteHandle; |
|
731 self->iAttributesSupported = (aConsoleWriteHandle.SetAttributes(0) == KErrNone); |
|
732 return self; |
|
733 } |
|
734 |
|
735 EXPORT_C CTextFormatter::~CTextFormatter() |
|
736 { |
|
737 } |
|
738 |
|
739 CTextFormatter::CTextFormatter(TInt aAvailableWidth) |
|
740 : iAvailableWidth(aAvailableWidth - 1) |
|
741 { |
|
742 } |
|
743 |
|
744 void CTextFormatter::ConstructL() |
|
745 { |
|
746 CTextBuffer::ConstructL(0x100); |
|
747 } |
|
748 |
|
749 EXPORT_C void CTextFormatter::WrapL(TInt aIndent, const TDesC& aText) |
|
750 { |
|
751 AppendSpacesL(aIndent); |
|
752 WrapL(aIndent, aIndent, aText); |
|
753 } |
|
754 |
|
755 EXPORT_C void CTextFormatter::WrapL(TInt aStartPosition, TInt aIndent, const TDesC& aText) |
|
756 { |
|
757 TUint originalAttributes = ConsoleAttributes::ENone; |
|
758 ConsoleAttributes::TColor foregroundColor = ConsoleAttributes::EUnchanged; |
|
759 ConsoleAttributes::TColor backgroundColor = ConsoleAttributes::EUnchanged; |
|
760 if (iAttributesSupported) |
|
761 { |
|
762 GetCurrentAttributes(originalAttributes, foregroundColor, backgroundColor); |
|
763 } |
|
764 |
|
765 CTextBuffer* buffer = CTextBuffer::NewLC(0x100); |
|
766 DecodeInteriorPodSequencesL(aText, *buffer); |
|
767 TLex lex(buffer->Descriptor()); |
|
768 TInt linePos = aStartPosition; |
|
769 while (!lex.Eos()) |
|
770 { |
|
771 lex.Mark(); |
|
772 lex.SkipSpace(); |
|
773 TPtrC whiteSpace(lex.MarkedToken()); |
|
774 if (whiteSpace.Length() > 0) |
|
775 { |
|
776 TInt newLinePos; |
|
777 do |
|
778 { |
|
779 newLinePos = whiteSpace.Find(KNewLine); |
|
780 if (newLinePos >= 0) |
|
781 { |
|
782 AppendSpacesL(iAvailableWidth - linePos - 1); |
|
783 AppendL(KNewLine); |
|
784 AppendSpacesL(aIndent); |
|
785 linePos = aIndent; |
|
786 whiteSpace.Set(whiteSpace.Mid(newLinePos + KNewLine().Length())); |
|
787 } |
|
788 } |
|
789 while (newLinePos >= 0); |
|
790 |
|
791 if (iAvailableWidth < whiteSpace.Length()) |
|
792 { |
|
793 AppendSpacesL(iAvailableWidth - linePos - 1); |
|
794 AppendL(KNewLine); |
|
795 AppendSpacesL(aIndent); |
|
796 linePos = aIndent; |
|
797 } |
|
798 else |
|
799 { |
|
800 AppendL(whiteSpace); |
|
801 linePos += whiteSpace.Length(); |
|
802 } |
|
803 } |
|
804 |
|
805 lex.Mark(); |
|
806 lex.SkipCharacters(); |
|
807 TPtrC word(lex.MarkedToken()); |
|
808 const TInt wordLength = word.Length(); |
|
809 if (wordLength > 0) |
|
810 { |
|
811 if ((linePos + wordLength + KNewLine().Length()) > iAvailableWidth) |
|
812 { |
|
813 AppendL(KNewLine); |
|
814 AppendSpacesL(aIndent); |
|
815 linePos = aIndent; |
|
816 } |
|
817 |
|
818 if (iAttributesSupported) |
|
819 { |
|
820 for (TInt i = 0; i < wordLength; ++i) |
|
821 { |
|
822 TUint attributes; |
|
823 buffer->GetAttributes(lex.Offset() - wordLength + i, attributes, foregroundColor, backgroundColor); |
|
824 SetAttributesL(originalAttributes | attributes, foregroundColor, backgroundColor); |
|
825 AppendL(word[i]); |
|
826 } |
|
827 } |
|
828 else |
|
829 { |
|
830 AppendL(word); |
|
831 } |
|
832 linePos += wordLength; |
|
833 } |
|
834 } |
|
835 |
|
836 CleanupStack::PopAndDestroy(buffer); |
|
837 SetAttributesL(originalAttributes, foregroundColor, backgroundColor); |
|
838 } |
|
839 |
|
840 EXPORT_C void CTextFormatter::TabulateL(TInt aIndent, TInt aGap, const TDesC& aText) |
|
841 { |
|
842 TabulateL(aIndent, aGap, aText, EWrapLastColumn); |
|
843 } |
|
844 |
|
845 EXPORT_C void CTextFormatter::TabulateL(TInt aIndent, TInt aGap, const TDesC& aText, TTabMode aMode) |
|
846 { |
|
847 CTextBuffer* scratchBuffer = NULL; |
|
848 RArray<TInt> columnWidths; |
|
849 CleanupClosePushL(columnWidths); |
|
850 TLex lineLexer(aText); |
|
851 |
|
852 // Find column widths. |
|
853 TPtrC line; |
|
854 while (NextLine(lineLexer, line)) |
|
855 { |
|
856 TLex columnLexer(line); |
|
857 TInt col = 0; |
|
858 TPtrC column; |
|
859 while (NextColumn(columnLexer, column)) |
|
860 { |
|
861 if (col >= columnWidths.Count()) |
|
862 { |
|
863 User::LeaveIfError(columnWidths.Append(aGap)); |
|
864 } |
|
865 TInt thisColumnWidth = ActualLength(column); |
|
866 if (columnWidths[col] < (thisColumnWidth + aGap)) |
|
867 { |
|
868 columnWidths[col] = (thisColumnWidth + aGap); |
|
869 } |
|
870 ++col; |
|
871 } |
|
872 } |
|
873 |
|
874 const TInt numCols = columnWidths.Count(); |
|
875 |
|
876 if (numCols == 0) |
|
877 { |
|
878 // No columns found, so just copy aText directly. |
|
879 AppendL(aText); |
|
880 CleanupStack::PopAndDestroy(&columnWidths); |
|
881 return; |
|
882 } |
|
883 |
|
884 if (aMode == EWrapLastColumn) |
|
885 { |
|
886 // Find the widest of all but the last column. |
|
887 TInt sum = aIndent; |
|
888 for (TInt i = 0; i < (numCols - 1); ++i) |
|
889 { |
|
890 sum += columnWidths[i]; |
|
891 } |
|
892 TInt remainingSpace = iAvailableWidth - sum; |
|
893 if (remainingSpace < 0) |
|
894 { |
|
895 // If you hit this, it means that the text cannot be columnised because the columns preceding the last one take up more space than the overall. |
|
896 User::Leave(KErrTooBig); // Let's go for something marginally more descriptive than KErrGeneral |
|
897 } |
|
898 // Assign the remaining space to the last column (which will be wrapped). |
|
899 columnWidths[numCols - 1] = remainingSpace; |
|
900 } |
|
901 else if (aMode == ETruncateLongestColumn) |
|
902 { |
|
903 // Find the total width of all the columns. |
|
904 TInt sum = aIndent; |
|
905 for (TInt i = 0; i < numCols; ++i) |
|
906 { |
|
907 sum += columnWidths[i]; |
|
908 } |
|
909 TInt excess = iAvailableWidth - sum; |
|
910 if (excess < 0) |
|
911 { |
|
912 // Not enough space, so steal from the widest column until there is. |
|
913 while (excess < 0) |
|
914 { |
|
915 TInt widestColumn = -1; |
|
916 TInt widestColumnWidth = 0; |
|
917 for (TInt i = 0; i < numCols; ++i) |
|
918 { |
|
919 if (columnWidths[i] > widestColumnWidth) |
|
920 { |
|
921 widestColumnWidth = columnWidths[i]; |
|
922 widestColumn = i; |
|
923 } |
|
924 } |
|
925 if (widestColumn < 0) |
|
926 { |
|
927 User::Leave(KErrGeneral); |
|
928 } |
|
929 --columnWidths[widestColumn]; |
|
930 ++excess; |
|
931 } |
|
932 } |
|
933 else |
|
934 { |
|
935 // Assign execess to the last column. |
|
936 columnWidths[numCols - 1] += excess; |
|
937 } |
|
938 } |
|
939 else if (aMode == EIgnoreAvailableWidth) |
|
940 { |
|
941 // just use the column widths we've already worked out, no matter if they're too wide. |
|
942 } |
|
943 else |
|
944 { |
|
945 ASSERT(EFalse); |
|
946 } |
|
947 |
|
948 // Write formatted text to the buffer. |
|
949 lineLexer = TLex(aText); |
|
950 TInt linePos = 0; |
|
951 while (NextLine(lineLexer, line)) |
|
952 { |
|
953 AppendSpacesL(aIndent); |
|
954 linePos += aIndent; |
|
955 TLex columnLexer(line); |
|
956 TInt col = 0; |
|
957 TPtrC column; |
|
958 while (NextColumn(columnLexer, column)) |
|
959 { |
|
960 TBool isLastColumn(col == (numCols - 1)); |
|
961 const TInt columnWidth = columnWidths[col]; |
|
962 if ((aMode == ETruncateLongestColumn) || !isLastColumn) |
|
963 { |
|
964 if (scratchBuffer == NULL) |
|
965 { |
|
966 scratchBuffer = CTextBuffer::NewLC(0x100); |
|
967 } |
|
968 else |
|
969 { |
|
970 scratchBuffer->Zero(); |
|
971 } |
|
972 DecodeInteriorPodSequencesL(column, *scratchBuffer); |
|
973 TInt availableWidth = columnWidth; |
|
974 if (!isLastColumn) |
|
975 { |
|
976 availableWidth -= aGap; |
|
977 } |
|
978 if (scratchBuffer->Descriptor().Length() > availableWidth) |
|
979 { |
|
980 scratchBuffer->Delete(availableWidth, scratchBuffer->Descriptor().Length() - availableWidth); |
|
981 } |
|
982 AppendL(*scratchBuffer); |
|
983 AppendSpacesL(columnWidth - scratchBuffer->Descriptor().Length()); |
|
984 linePos += columnWidth; |
|
985 } |
|
986 else if (aMode == EIgnoreAvailableWidth) |
|
987 { |
|
988 AppendL(column); |
|
989 if (!isLastColumn) |
|
990 { |
|
991 AppendSpacesL(columnWidth - column.Length()); |
|
992 } |
|
993 linePos += columnWidth; |
|
994 } |
|
995 else |
|
996 { |
|
997 WrapL(linePos, linePos, column); |
|
998 } |
|
999 ++col; |
|
1000 } |
|
1001 AppendL(KNewLine); |
|
1002 linePos = 0; |
|
1003 } |
|
1004 |
|
1005 if (scratchBuffer) |
|
1006 { |
|
1007 CleanupStack::PopAndDestroy(scratchBuffer); |
|
1008 } |
|
1009 CleanupStack::PopAndDestroy(&columnWidths); |
|
1010 } |
|
1011 |
|
1012 EXPORT_C void CTextFormatter::ColumnizeL(TInt aIndent, TInt aGap, const TDesC& aText) |
|
1013 { |
|
1014 // Store the tab delimited text as an array of TPtrCs. |
|
1015 RArray<TPtrC> items; |
|
1016 CleanupClosePushL(items); |
|
1017 TLex lex(aText); |
|
1018 TPtrC column; |
|
1019 while (NextColumn(lex, column)) |
|
1020 { |
|
1021 User::LeaveIfError(items.Append(column)); |
|
1022 } |
|
1023 ColumnizeL(aIndent, aGap, items.Array()); |
|
1024 CleanupStack::PopAndDestroy(1, &items); |
|
1025 } |
|
1026 |
|
1027 EXPORT_C void CTextFormatter::ColumnizeL(TInt aIndent, TInt aGap, const TArray<TPtrC>& aItems) |
|
1028 { |
|
1029 // Lays out tab delimited data as a set of columns that read like a news paper |
|
1030 // (i.e. starting with the left most column, you read down to the bottom of it |
|
1031 // and then start reading the next column from the top, etc.). |
|
1032 |
|
1033 // Determine the smallest number of rows that allows all the data to fit |
|
1034 // the available horizontal space. The algorithm works by iteratively increasing |
|
1035 // the number of rows from one until a fit is found. |
|
1036 const TInt numItems = aItems.Count(); |
|
1037 RArray<TInt> columnWidths; |
|
1038 CleanupClosePushL(columnWidths); |
|
1039 TInt numRows = 0; |
|
1040 TBool fits(EFalse); |
|
1041 while (!fits) |
|
1042 { |
|
1043 ++numRows; |
|
1044 columnWidths.Reset(); |
|
1045 TInt requiredWidth = aIndent; |
|
1046 TInt col = 0; |
|
1047 TInt i = 0; |
|
1048 while (i < numItems) |
|
1049 { |
|
1050 for (TInt row = 0; row < numRows; ++row) |
|
1051 { |
|
1052 if (columnWidths.Count() <= col) |
|
1053 { |
|
1054 User::LeaveIfError(columnWidths.Append(0)); |
|
1055 } |
|
1056 TInt thisItemWidth = ActualLength(aItems[i]); |
|
1057 if (thisItemWidth > columnWidths[col]) |
|
1058 { |
|
1059 columnWidths[col] = thisItemWidth; |
|
1060 } |
|
1061 if (++i >= numItems) |
|
1062 { |
|
1063 break; |
|
1064 } |
|
1065 } |
|
1066 requiredWidth += columnWidths[col]; |
|
1067 if ((requiredWidth + aGap) > iAvailableWidth) |
|
1068 { |
|
1069 if ((requiredWidth + KNewLine().Length()) > iAvailableWidth) |
|
1070 { |
|
1071 if (col > 0) |
|
1072 { |
|
1073 // Not enough space with this number of rows, so try another row. |
|
1074 i = 0; |
|
1075 break; |
|
1076 } |
|
1077 else |
|
1078 { |
|
1079 // Not enough space even with just one column. Lay out as a single column anyway and accept ugly wrapping by the console. |
|
1080 CleanupStack::PopAndDestroy(1, &columnWidths); |
|
1081 for (TInt i = 0; i < numItems; ++i) |
|
1082 { |
|
1083 AppendSpacesL(aIndent); |
|
1084 AppendL(aItems[i]); |
|
1085 AppendL(KNewLine); |
|
1086 } |
|
1087 return; |
|
1088 } |
|
1089 } |
|
1090 else |
|
1091 { |
|
1092 requiredWidth += KNewLine().Length(); |
|
1093 } |
|
1094 } |
|
1095 else |
|
1096 { |
|
1097 requiredWidth += aGap; |
|
1098 } |
|
1099 ++col; |
|
1100 } |
|
1101 if (i >= numItems) |
|
1102 { |
|
1103 fits = ETrue; |
|
1104 } |
|
1105 } |
|
1106 |
|
1107 // Layout the columns. |
|
1108 const TInt numCols = columnWidths.Count(); |
|
1109 for (TInt row = 0; row < numRows; ++row) |
|
1110 { |
|
1111 AppendSpacesL(aIndent); |
|
1112 for (TInt col = 0; col < numCols; ++col) |
|
1113 { |
|
1114 TInt index = (numRows * col) + row; |
|
1115 if (index < numItems) |
|
1116 { |
|
1117 TPtrC item(aItems[index]); |
|
1118 DoAppendPodL(item); |
|
1119 TInt gap = (col == (numCols - 1)) ? 0 : aGap; |
|
1120 AppendSpacesL((columnWidths[col] + gap) - ActualLength(item)); |
|
1121 } |
|
1122 } |
|
1123 AppendL(KNewLine); |
|
1124 } |
|
1125 |
|
1126 CleanupStack::PopAndDestroy(1, &columnWidths); |
|
1127 } |
|
1128 |
|
1129 EXPORT_C void CTextFormatter::AppendPodL(const TDesC& aPod) |
|
1130 { |
|
1131 TPodFormatter podFormatter(*this); |
|
1132 podFormatter.FormatL(aPod); |
|
1133 } |
|
1134 |
|
1135 EXPORT_C TInt CTextFormatter::Write() |
|
1136 { |
|
1137 return CTextBuffer::Write(*iWriteHandle); |
|
1138 } |
|
1139 |
|
1140 void CTextFormatter::DoAppendPodL(const TDesC& aPod) |
|
1141 { |
|
1142 DecodeInteriorPodSequencesL(aPod, *this); |
|
1143 } |
|
1144 |
|
1145 void CTextFormatter::DecodeInteriorPodSequencesL(const TDesC& aPod, CTextBuffer& aBuffer) const |
|
1146 { |
|
1147 TPodLexer lexer(aPod); |
|
1148 TBool eop(EFalse); |
|
1149 TBool eos(EFalse); |
|
1150 |
|
1151 TUint originalAttributes = ConsoleAttributes::ENone; |
|
1152 ConsoleAttributes::TColor foregroundColor = ConsoleAttributes::EUnchanged; |
|
1153 ConsoleAttributes::TColor backgroundColor = ConsoleAttributes::EUnchanged; |
|
1154 if (iAttributesSupported) |
|
1155 { |
|
1156 aBuffer.GetCurrentAttributes(originalAttributes, foregroundColor, backgroundColor); |
|
1157 } |
|
1158 TUint currentAttributes = originalAttributes; |
|
1159 |
|
1160 while (!eos) |
|
1161 { |
|
1162 TPtrC token; |
|
1163 TPodLexer::TTokenType tokenType; |
|
1164 TUint attributes; |
|
1165 lexer.NextTokenL(token, tokenType, attributes, eop, eos); |
|
1166 |
|
1167 switch (tokenType) |
|
1168 { |
|
1169 case TPodLexer::EAttributePush: |
|
1170 case TPodLexer::EAttributePop: |
|
1171 if (!iAttributesSupported && (attributes & TPodLexer::EBold)) |
|
1172 { |
|
1173 aBuffer.AppendL('*'); |
|
1174 } |
|
1175 else if (!iAttributesSupported && (attributes & TPodLexer::EItalic)) |
|
1176 { |
|
1177 aBuffer.AppendL('\''); |
|
1178 } |
|
1179 else if ((!iAttributesSupported && (attributes & TPodLexer::EFileName)) || (attributes & TPodLexer::TPodLexer::ECode)) |
|
1180 { |
|
1181 aBuffer.AppendL('"'); |
|
1182 } |
|
1183 break; |
|
1184 case TPodLexer::ELink: |
|
1185 { |
|
1186 TInt pos = token.Locate('|'); |
|
1187 if (pos >= 0) |
|
1188 { |
|
1189 token.Set(token.Left(pos)); |
|
1190 } |
|
1191 } |
|
1192 // Deliberate fall through. |
|
1193 case TPodLexer::ETextBlock: |
|
1194 case TPodLexer::ECodeBlock: |
|
1195 case TPodLexer::EIndexEntry: |
|
1196 if (iAttributesSupported) |
|
1197 { |
|
1198 if ((attributes == 0) || (attributes & (TPodLexer::ENull | TPodLexer::ECode))) |
|
1199 { |
|
1200 currentAttributes = originalAttributes; |
|
1201 } |
|
1202 if (attributes & (TPodLexer::EBold | TPodLexer::EItalic | TPodLexer::EFileName)) |
|
1203 { |
|
1204 currentAttributes |= ConsoleAttributes::EBold; |
|
1205 } |
|
1206 aBuffer.SetAttributesL(currentAttributes); |
|
1207 } |
|
1208 aBuffer.AppendL(token); |
|
1209 break; |
|
1210 default: |
|
1211 ASSERT(EFalse); |
|
1212 } |
|
1213 } |
|
1214 |
|
1215 if (iAttributesSupported && (currentAttributes != originalAttributes)) |
|
1216 { |
|
1217 aBuffer.SetAttributesL(originalAttributes); |
|
1218 } |
|
1219 } |
|
1220 |
|
1221 EXPORT_C void CTextFormatter::Zero() |
|
1222 { |
|
1223 CTextBuffer::Zero(); |
|
1224 } |
|
1225 |
|
1226 EXPORT_C void CTextFormatter::Reset() |
|
1227 { |
|
1228 CTextBuffer::Reset(); |
|
1229 } |
|
1230 |
|
1231 EXPORT_C void CTextFormatter::ResetText() |
|
1232 { |
|
1233 CTextBuffer::ResetText(); |
|
1234 } |
|
1235 |
|
1236 TBool CTextFormatter::NextColumn(TLex& aLex, TPtrC& aPtr) const |
|
1237 { |
|
1238 aLex.Mark(); |
|
1239 while (!aLex.Eos()) |
|
1240 { |
|
1241 if (aLex.Get() == '\t') |
|
1242 { |
|
1243 aLex.UnGet(); |
|
1244 aPtr.Set(aLex.MarkedToken()); |
|
1245 aLex.Get(); |
|
1246 return ETrue; |
|
1247 } |
|
1248 } |
|
1249 if (aLex.TokenLength() > 0) |
|
1250 { |
|
1251 aPtr.Set(aLex.MarkedToken()); |
|
1252 return ETrue; |
|
1253 } |
|
1254 return EFalse; |
|
1255 } |
|
1256 |
|
1257 TBool CTextFormatter::NextLine(TLex& aLex, TPtrC& aPtr) const |
|
1258 { |
|
1259 aLex.Mark(); |
|
1260 while (!aLex.Eos()) |
|
1261 { |
|
1262 TChar ch = aLex.Get(); |
|
1263 if (ch == '\r') |
|
1264 { |
|
1265 if (aLex.Get() == '\n') |
|
1266 { |
|
1267 aLex.UnGet(); |
|
1268 aLex.UnGet(); |
|
1269 aPtr.Set(aLex.MarkedToken()); |
|
1270 aLex.Get(); |
|
1271 aLex.Get(); |
|
1272 return ETrue; |
|
1273 } |
|
1274 else |
|
1275 { |
|
1276 aLex.UnGet(); |
|
1277 } |
|
1278 } |
|
1279 } |
|
1280 if (aLex.TokenLength() > 0) |
|
1281 { |
|
1282 aPtr.Set(aLex.MarkedToken()); |
|
1283 return ETrue; |
|
1284 } |
|
1285 return EFalse; |
|
1286 } |
|
1287 |
|
1288 TInt CTextFormatter::ActualLength(const TDesC& aPod) const |
|
1289 { |
|
1290 CTextBuffer* buffer = CTextBuffer::NewLC(0x100); |
|
1291 DecodeInteriorPodSequencesL(aPod, *buffer); |
|
1292 TInt length = buffer->Descriptor().Length(); |
|
1293 CleanupStack::PopAndDestroy(buffer); |
|
1294 return length; |
|
1295 } |