|
1 // guicons.cpp |
|
2 // |
|
3 // Copyright (c) 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 <fshell/common.mmh> |
|
14 #include "guicons.h" |
|
15 #include <ImageConversion.h> |
|
16 #include <e32Math.h> |
|
17 |
|
18 #include "defaultfontdata.inl" |
|
19 |
|
20 const TInt KAttributeMapGranularity = 3; |
|
21 |
|
22 const ConsoleAttributes::TColor KDefaultForegroundColor = ConsoleAttributes::EBlack; |
|
23 const ConsoleAttributes::TColor KDefaultBackgroundColor = ConsoleAttributes::EWhite; |
|
24 |
|
25 |
|
26 ConsoleAttributes::TAttributes DefaultAttributes() |
|
27 { |
|
28 return ConsoleAttributes::TAttributes(ConsoleAttributes::ENone, KDefaultForegroundColor, KDefaultBackgroundColor); |
|
29 } |
|
30 |
|
31 TRgb MapColor(TUint aAttributes, ConsoleAttributes::TColor aColor) |
|
32 { |
|
33 TRgb rgb; |
|
34 |
|
35 switch (aColor) |
|
36 { |
|
37 case ConsoleAttributes::EBlack: |
|
38 if (aAttributes & ConsoleAttributes::EBold) |
|
39 { |
|
40 rgb = KRgbGray; |
|
41 } |
|
42 else |
|
43 { |
|
44 rgb = KRgbBlack; |
|
45 } |
|
46 break; |
|
47 case ConsoleAttributes::ERed: |
|
48 if (aAttributes & ConsoleAttributes::EBold) |
|
49 { |
|
50 rgb = KRgbRed; |
|
51 } |
|
52 else |
|
53 { |
|
54 rgb = KRgbDarkRed; |
|
55 } |
|
56 break; |
|
57 case ConsoleAttributes::EGreen: |
|
58 if (aAttributes & ConsoleAttributes::EBold) |
|
59 { |
|
60 rgb = KRgbGreen; |
|
61 } |
|
62 else |
|
63 { |
|
64 rgb = KRgbDarkGreen; |
|
65 } |
|
66 break; |
|
67 case ConsoleAttributes::EYellow: |
|
68 if (aAttributes & ConsoleAttributes::EBold) |
|
69 { |
|
70 rgb = KRgbYellow; |
|
71 } |
|
72 else |
|
73 { |
|
74 rgb = KRgbDarkYellow; |
|
75 } |
|
76 break; |
|
77 case ConsoleAttributes::EBlue: |
|
78 if (aAttributes & ConsoleAttributes::EBold) |
|
79 { |
|
80 rgb = KRgbBlue; |
|
81 } |
|
82 else |
|
83 { |
|
84 rgb = KRgbDarkBlue; |
|
85 } |
|
86 break; |
|
87 case ConsoleAttributes::EMagenta: |
|
88 if (aAttributes & ConsoleAttributes::EBold) |
|
89 { |
|
90 rgb = KRgbMagenta; |
|
91 } |
|
92 else |
|
93 { |
|
94 rgb = KRgbDarkMagenta; |
|
95 } |
|
96 break; |
|
97 case ConsoleAttributes::ECyan: |
|
98 if (aAttributes & ConsoleAttributes::EBold) |
|
99 { |
|
100 rgb = KRgbCyan; |
|
101 } |
|
102 else |
|
103 { |
|
104 rgb = KRgbDarkCyan; |
|
105 } |
|
106 break; |
|
107 case ConsoleAttributes::EWhite: |
|
108 if (aAttributes & ConsoleAttributes::EBold) |
|
109 { |
|
110 rgb = KRgbWhite; |
|
111 } |
|
112 else |
|
113 { |
|
114 rgb = KRgbWhite;//KRgbGray; |
|
115 } |
|
116 break; |
|
117 case ConsoleAttributes::EReset: |
|
118 case ConsoleAttributes::EUnchanged: |
|
119 default: |
|
120 ASSERT(EFalse); |
|
121 } |
|
122 |
|
123 if (aAttributes & ConsoleAttributes::EInverse) |
|
124 { |
|
125 rgb = ~rgb; |
|
126 } |
|
127 |
|
128 return rgb; |
|
129 } |
|
130 |
|
131 void SignalSemaphore(TAny* aSemaphore) |
|
132 { |
|
133 ((RSemaphore*)aSemaphore)->Signal(); |
|
134 } |
|
135 |
|
136 void CleanupSignalSemaphorePushL(RSemaphore& aSemaphore) |
|
137 { |
|
138 CleanupStack::PushL(TCleanupItem(SignalSemaphore, &aSemaphore)); |
|
139 } |
|
140 |
|
141 void WaitForRequest(TAny* aStatus) |
|
142 { |
|
143 User::WaitForRequest(*(TRequestStatus*)aStatus); |
|
144 } |
|
145 |
|
146 void CleanupWaitForRequestPushL(TRequestStatus& aStatus) |
|
147 { |
|
148 CleanupStack::PushL(TCleanupItem(WaitForRequest, &aStatus)); |
|
149 } |
|
150 |
|
151 //______________________________________________________________________________ |
|
152 // CConsoleControl |
|
153 EXPORT_C CConsoleControl* CConsoleControl::NewL(TInt aBufferSize, MConsoleUi* aUi) |
|
154 { |
|
155 CConsoleControl* self = new(ELeave)CConsoleControl(aUi, aBufferSize); |
|
156 CleanupStack::PushL(self); |
|
157 self->ConstructL(CConsoleFont::NewL(KDefaultFontImageData)); |
|
158 CleanupStack::Pop(self); |
|
159 return self; |
|
160 } |
|
161 |
|
162 EXPORT_C CConsoleControl* CConsoleControl::NewL(TInt aBufferSize, const TDesC& aFontFile, MConsoleUi* aUi) |
|
163 { |
|
164 CConsoleControl* self = new(ELeave)CConsoleControl(aUi, aBufferSize); |
|
165 CleanupStack::PushL(self); |
|
166 self->ConstructL(CConsoleFont::NewL(aFontFile)); |
|
167 CleanupStack::Pop(self); |
|
168 return self; |
|
169 } |
|
170 |
|
171 EXPORT_C CConsoleControl::~CConsoleControl() |
|
172 { |
|
173 delete iBlinkTimer; |
|
174 delete iFont; |
|
175 iCursor.Hide(); |
|
176 iBuffer.ResetAndDestroy(); |
|
177 iKeyQueue.Close(); |
|
178 } |
|
179 |
|
180 EXPORT_C void CConsoleControl::Closed() |
|
181 { |
|
182 if (iUi) |
|
183 { |
|
184 iUi->HandleConsoleClosed(this); |
|
185 } |
|
186 } |
|
187 |
|
188 EXPORT_C void CConsoleControl::Draw(const TRect& aRect) const |
|
189 { |
|
190 CWindowGc& gc = SystemGc(); |
|
191 gc.SetBrushStyle(CGraphicsContext::ENullBrush); |
|
192 gc.SetPenStyle(CGraphicsContext::ENullPen); |
|
193 // Need to do a clear here, to ensure we actually draw to all the pixels in aRect that we've been asked to draw. If we don't do that, wserv generally gets upset. |
|
194 // gc.SetBrushColor(KDefaultBackgroundColor); |
|
195 // gc.Clear(aRect); |
|
196 |
|
197 for (TInt y=0; y<iSizeChars.iHeight; ++y) |
|
198 { |
|
199 TViewPosition line(*this, 0, y); |
|
200 if (aRect.Intersects(LineRect(line))) |
|
201 { |
|
202 DrawLine(line, gc); |
|
203 } |
|
204 } |
|
205 |
|
206 if (iDrawNavigator) |
|
207 { |
|
208 // And draw the 5-way UI |
|
209 #ifdef FSHELL_WSERV2_SUPPORT |
|
210 // XOR draw mode doesn't seem to be supported in recent wserv, so use a colour with alpha channel instead |
|
211 const TRgb col(15, 15, 15, 128); |
|
212 gc.SetDrawMode(CGraphicsContext::EDrawModePEN); |
|
213 #else |
|
214 const TRgb col(15,15,15); |
|
215 gc.SetDrawMode(CGraphicsContext::EDrawModeXOR); |
|
216 #endif |
|
217 gc.SetBrushColor(col); |
|
218 gc.SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
219 gc.SetPenColor(col); |
|
220 for (TInt i = 0; i < ENumButtons; i++) |
|
221 { |
|
222 if (aRect.Intersects(iButtonRects[i])) |
|
223 { |
|
224 if (i == ECenter) |
|
225 { |
|
226 gc.DrawEllipse(iButtonRects[i]); |
|
227 } |
|
228 else |
|
229 { |
|
230 gc.DrawRect(iButtonRects[i]); |
|
231 } |
|
232 } |
|
233 } |
|
234 } |
|
235 } |
|
236 |
|
237 EXPORT_C TCoeInputCapabilities CConsoleControl::InputCapabilities() const |
|
238 { |
|
239 return TCoeInputCapabilities( |
|
240 TCoeInputCapabilities::ENonPredictive |
|
241 | TCoeInputCapabilities::EAllText |
|
242 | TCoeInputCapabilities::ENavigation |
|
243 ); |
|
244 } |
|
245 |
|
246 EXPORT_C void CConsoleControl::FocusChanged(TDrawNow) |
|
247 { |
|
248 iCursor.Update(); |
|
249 if (IsFocused()) |
|
250 { |
|
251 StartBlinking(); |
|
252 } |
|
253 else |
|
254 { |
|
255 iBlinkTimer->Cancel(); |
|
256 } |
|
257 } |
|
258 |
|
259 EXPORT_C void CConsoleControl::HandlePointerEventL(const TPointerEvent& aPointerEvent) |
|
260 { |
|
261 if (aPointerEvent.iType == TPointerEvent::EButton1Down) |
|
262 { |
|
263 for (TInt i = 0; i < ENumButtons; i++) |
|
264 { |
|
265 if (iButtonRects[i].Contains(aPointerEvent.iPosition)) |
|
266 { |
|
267 SimulateKeyL((TButton)i); |
|
268 iIgnoringDrags = ETrue; |
|
269 return; |
|
270 } |
|
271 } |
|
272 iIgnoringDrags = EFalse; |
|
273 } |
|
274 |
|
275 if (iIgnoringDrags) return; |
|
276 if (aPointerEvent.iType == TPointerEvent::EButton1Down) |
|
277 { |
|
278 iDragStart = aPointerEvent.iPosition; |
|
279 } |
|
280 if (aPointerEvent.iType == TPointerEvent::EDrag) |
|
281 { |
|
282 TPoint delta = iDragStart - aPointerEvent.iPosition; |
|
283 TInt lines = delta.iY / iFont->GlyphSize().iHeight; |
|
284 if (lines) |
|
285 { |
|
286 iViewWindow.iY += lines; |
|
287 ViewMoved(); |
|
288 |
|
289 iDragStart.iY -= (lines * iFont->GlyphSize().iHeight); |
|
290 } |
|
291 } |
|
292 } |
|
293 |
|
294 EXPORT_C TKeyResponse CConsoleControl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) |
|
295 { |
|
296 if ((!IsFocused()) || IsNonFocusing()) return EKeyWasNotConsumed; |
|
297 |
|
298 if (aType == EEventKey) |
|
299 { |
|
300 iKeyQueue.AppendL(aKeyEvent); |
|
301 SendKey(); |
|
302 |
|
303 #ifdef LOCAL_ECHO |
|
304 TUint code = aKeyEvent.iCode; |
|
305 if (code == '\r') code = '\n'; |
|
306 |
|
307 TBuf<0x20> ip; |
|
308 ip.AppendFormat(_L("key %d"), code); |
|
309 User::InfoPrint(ip); |
|
310 |
|
311 TBuf<1> buf; |
|
312 buf.Append(TChar(code)); |
|
313 Write(buf); |
|
314 #endif |
|
315 return EKeyWasConsumed; |
|
316 } |
|
317 return EKeyWasNotConsumed; |
|
318 } |
|
319 |
|
320 EXPORT_C void CConsoleControl::InjectKeysL(const TDesC& aKeys) |
|
321 { |
|
322 for (TInt i=0; i<aKeys.Length(); ++i) |
|
323 { |
|
324 TKeyEvent key; |
|
325 key.iCode = aKeys[i]; |
|
326 key.iModifiers = 0; |
|
327 iKeyQueue.AppendL(key); |
|
328 } |
|
329 SendKey(); |
|
330 } |
|
331 |
|
332 void CConsoleControl::DrawLine(TViewPosition aLine, CBitmapContext& aDrawTo) const |
|
333 { |
|
334 CConsoleLine* line = GetLine(aLine); |
|
335 if (line) |
|
336 { |
|
337 line->Draw(aDrawTo, aLine); |
|
338 } |
|
339 } |
|
340 |
|
341 TRect CConsoleControl::LineRect(TViewPosition aLine) const |
|
342 { |
|
343 return TRect(TScreenPosition(aLine).iPoint, TSize(iFont->GlyphSize().iWidth * iSizeChars.iWidth, iFont->GlyphSize().iHeight)); |
|
344 } |
|
345 |
|
346 |
|
347 EXPORT_C void CConsoleControl::SizeChanged() |
|
348 { |
|
349 TSize sizePixels = Size(); |
|
350 TSize newSizeChars(sizePixels.iWidth / iFont->GlyphSize().iWidth, sizePixels.iHeight / iFont->GlyphSize().iHeight); |
|
351 if (newSizeChars != iSizeChars) |
|
352 { |
|
353 iSizeChars = newSizeChars; |
|
354 TRAP_IGNORE(SizeChangedL()); |
|
355 } |
|
356 } |
|
357 |
|
358 CConsoleControl::CConsoleControl(MConsoleUi* aUi, TInt aBufferSize) |
|
359 : iUi(aUi), iCursor(*this), iCurrentAttributes(ConsoleAttributes::ENone, KDefaultForegroundColor, KDefaultBackgroundColor), iBufferSize(aBufferSize) |
|
360 { |
|
361 } |
|
362 |
|
363 void CConsoleControl::ConstructL(CConsoleFont* aFont) |
|
364 { |
|
365 iBlinkTimer = CPeriodic::NewL(CActive::EPriorityStandard); |
|
366 iFont = aFont; |
|
367 iCursor.SetFont(*iFont); |
|
368 SetCursorHeight(KDefaultCursorHeightPercentage); |
|
369 } |
|
370 |
|
371 void CConsoleControl::SizeChangedL() |
|
372 { |
|
373 TInt bufferSize = Max(iBufferSize, iSizeChars.iHeight); |
|
374 for (TInt i=0; i<Min(iBuffer.Count(), bufferSize); ++i) |
|
375 { |
|
376 iBuffer[i]->SetWidthL(iSizeChars.iWidth); |
|
377 } |
|
378 while (iBuffer.Count() < bufferSize) |
|
379 { |
|
380 CConsoleLine* line = CConsoleLine::NewL(*this, *iFont, iSizeChars.iWidth); |
|
381 CleanupStack::PushL(line); |
|
382 iBuffer.AppendL(line); |
|
383 CleanupStack::Pop(); |
|
384 } |
|
385 while (iBuffer.Count() > bufferSize) |
|
386 { |
|
387 delete iBuffer[iBuffer.Count()-1]; |
|
388 iBuffer.Remove(iBuffer.Count()-1); |
|
389 } |
|
390 iCursor.Update(); |
|
391 |
|
392 if (FivewayNavIsDisplaying()) SetDisplayFivewayNav(ETrue); // re-layout the onscreen nav if applicable |
|
393 } |
|
394 |
|
395 CConsoleLine* CConsoleControl::GetLine(TBufferPosition aLine) const |
|
396 { |
|
397 return iBuffer[aLine.iPoint.iY]; |
|
398 } |
|
399 |
|
400 TPoint CConsoleControl::ViewPosition() const |
|
401 { |
|
402 return iViewWindow; |
|
403 } |
|
404 |
|
405 TPoint CConsoleControl::CursorWindowPosition() const |
|
406 { |
|
407 return iCursorWindow; |
|
408 } |
|
409 |
|
410 TSize CConsoleControl::GlyphSize() const |
|
411 { |
|
412 return iFont->GlyphSize(); |
|
413 } |
|
414 |
|
415 TBool CConsoleControl::IsSpecialChar(TChar aChar) const |
|
416 { |
|
417 switch(aChar) |
|
418 { |
|
419 case 0x00: // Null. |
|
420 case 0x07: // Bell. |
|
421 case 0x08: // Backspace. |
|
422 case 0x7f: // Delete. |
|
423 case 0x09: // Tab. |
|
424 case 0x0a: // Line feed. |
|
425 case 0x0b: // Vertical tab. |
|
426 case 0x0c: // Form feed. |
|
427 case 0x0d: // Carriage return. |
|
428 return ETrue; |
|
429 default: |
|
430 return EFalse; |
|
431 } |
|
432 } |
|
433 |
|
434 void CConsoleControl::HandleSpecialChar(TChar aChar) |
|
435 { |
|
436 switch(aChar) |
|
437 { |
|
438 case 0x00: // Null. |
|
439 break; |
|
440 case 0x07: // Bell. |
|
441 break; |
|
442 case 0x08: // Backspace. |
|
443 case 0x7f: // Delete. |
|
444 iCursor--; |
|
445 break; |
|
446 case 0x09: // horizontal tab |
|
447 iCursor += KTabSize - (iCursor.Position().iPoint.iX % KTabSize); |
|
448 break; |
|
449 case 0x0a: // line feed |
|
450 iCursor -= iCursor.Position().iPoint.iX; |
|
451 iCursor.Down(); |
|
452 break; |
|
453 case 0x0b: // Vertical tab. |
|
454 break; |
|
455 case 0x0c: // Form feed |
|
456 ClearScreen(); |
|
457 break; |
|
458 case 0x0d: // carriage return |
|
459 iCursor -= iCursor.Position().iPoint.iX; |
|
460 break; |
|
461 default: |
|
462 User::Invariant(); |
|
463 } |
|
464 } |
|
465 |
|
466 void CConsoleControl::SendKey() |
|
467 { |
|
468 if (iReader && iKeyQueue.Count()) |
|
469 { |
|
470 iCurrentKey = iKeyQueue[0]; |
|
471 iKeyQueue.Remove(0); |
|
472 iReader->ReadComplete(KErrNone); |
|
473 iReader = NULL; |
|
474 } |
|
475 } |
|
476 |
|
477 EXPORT_C void CConsoleControl::Read(MGuiConsoleReader& aReader) |
|
478 { |
|
479 if (iReader) |
|
480 { |
|
481 aReader.ReadComplete(KErrInUse); |
|
482 } |
|
483 else |
|
484 { |
|
485 iReader = &aReader; |
|
486 SendKey(); |
|
487 } |
|
488 } |
|
489 |
|
490 EXPORT_C void CConsoleControl::ReadCancel() |
|
491 { |
|
492 iReader = NULL; |
|
493 } |
|
494 |
|
495 EXPORT_C void CConsoleControl::Write(const TDesC &aDes) |
|
496 { |
|
497 TRAP_IGNORE(WriteL(aDes)); |
|
498 } |
|
499 |
|
500 void CConsoleControl::WriteL(const TDesC &aDes) |
|
501 { |
|
502 TRect invalidRect; |
|
503 for (TInt i=0; i<aDes.Length(); ++i) |
|
504 { |
|
505 if (IsSpecialChar(aDes[i])) |
|
506 { |
|
507 if (!invalidRect.IsEmpty()) |
|
508 { |
|
509 // Draw to the invalid rectangle before handling this special character because it may cause the |
|
510 // window to scroll, thereby invalidating the coordinates of invalidRect. |
|
511 DrawNow(invalidRect); |
|
512 invalidRect = TRect(); |
|
513 } |
|
514 HandleSpecialChar(aDes[i]); |
|
515 } |
|
516 else |
|
517 { |
|
518 CConsoleLine* line = GetLine(iCursor.Position()); |
|
519 line->SetL(iCursor.Position().iPoint.iX, aDes[i], iCurrentAttributes); |
|
520 TRect lineRect(LineRect(iCursor.Position())); |
|
521 Window().Invalidate(lineRect); |
|
522 if (invalidRect.IsEmpty()) |
|
523 { |
|
524 invalidRect = lineRect; |
|
525 } |
|
526 else |
|
527 { |
|
528 invalidRect.BoundingRect(lineRect); |
|
529 } |
|
530 iCursor++; |
|
531 } |
|
532 } |
|
533 |
|
534 if (!invalidRect.IsEmpty()) |
|
535 { |
|
536 DrawNow(invalidRect); |
|
537 } |
|
538 |
|
539 iCursor.Update(); |
|
540 } |
|
541 |
|
542 void CConsoleControl::StartBlinking() |
|
543 { |
|
544 if (!iBlinkTimer->IsActive()) |
|
545 { |
|
546 iBlinkTimer->Start(500000, 500000, TCallBack(BlinkCallback, this)); |
|
547 } |
|
548 } |
|
549 |
|
550 TInt CConsoleControl::BlinkCallback(TAny* aPtr) |
|
551 { |
|
552 CConsoleControl* self = static_cast<CConsoleControl*>(aPtr); |
|
553 |
|
554 TBool neededToBlink(EFalse); |
|
555 for (TInt y = 0; y < self->iSizeChars.iHeight; ++y) |
|
556 { |
|
557 TViewPosition line(*self, 0, y); |
|
558 if (self->GetLine(line)->NeedToBlink(self->iBlinkOn)) |
|
559 { |
|
560 neededToBlink = ETrue; |
|
561 self->Window().Invalidate(self->LineRect(line)); |
|
562 } |
|
563 } |
|
564 if (neededToBlink) |
|
565 { |
|
566 self->iBlinkOn = !self->iBlinkOn; |
|
567 } |
|
568 else |
|
569 { |
|
570 self->iBlinkTimer->Cancel(); |
|
571 } |
|
572 |
|
573 return KErrNone; |
|
574 } |
|
575 |
|
576 EXPORT_C void CConsoleControl::ViewScrollUp() |
|
577 { |
|
578 iViewWindow.iY--; |
|
579 ViewMoved(); |
|
580 } |
|
581 |
|
582 EXPORT_C void CConsoleControl::ViewScrollDown() |
|
583 { |
|
584 iViewWindow.iY++; |
|
585 ViewMoved(); |
|
586 } |
|
587 |
|
588 EXPORT_C void CConsoleControl::ViewPageUp() |
|
589 { |
|
590 iViewWindow.iY -= iSizeChars.iHeight-1; |
|
591 ViewMoved(); |
|
592 } |
|
593 |
|
594 EXPORT_C void CConsoleControl::ViewPageDown() |
|
595 { |
|
596 iViewWindow.iY += iSizeChars.iHeight-1; |
|
597 ViewMoved(); |
|
598 } |
|
599 |
|
600 EXPORT_C void CConsoleControl::ViewHome() |
|
601 { |
|
602 iViewWindow.iY = 0; |
|
603 ViewMoved(); |
|
604 } |
|
605 |
|
606 EXPORT_C void CConsoleControl::ViewEnd() |
|
607 { |
|
608 iViewWindow = iCursorWindow; |
|
609 ViewMoved(); |
|
610 } |
|
611 |
|
612 void CConsoleControl::Invalidate5Way() |
|
613 { |
|
614 if (iDrawNavigator) |
|
615 { |
|
616 for (TInt i = 0; i < ENumButtons; i++) |
|
617 { |
|
618 Window().Invalidate(iButtonRects[i]); |
|
619 } |
|
620 } |
|
621 } |
|
622 |
|
623 EXPORT_C TInt CConsoleControl::SetAttributes(TUint aAttributes, ConsoleAttributes::TColor aForegroundColor, ConsoleAttributes::TColor aBackgroundColor) |
|
624 { |
|
625 ConsoleAttributes::TAttributes currentAttributes = iCurrentAttributes; |
|
626 |
|
627 if (aAttributes == ConsoleAttributes::ENone) |
|
628 { |
|
629 currentAttributes = DefaultAttributes(); |
|
630 } |
|
631 else |
|
632 { |
|
633 currentAttributes.iAttributes = aAttributes; |
|
634 } |
|
635 |
|
636 switch (aForegroundColor) |
|
637 { |
|
638 case ConsoleAttributes::EReset: |
|
639 currentAttributes.iForegroundColor = KDefaultForegroundColor; |
|
640 break; |
|
641 case ConsoleAttributes::EUnchanged: |
|
642 // Do nothing. |
|
643 break; |
|
644 default: |
|
645 currentAttributes.iForegroundColor = aForegroundColor; |
|
646 break; |
|
647 } |
|
648 |
|
649 switch (aBackgroundColor) |
|
650 { |
|
651 case ConsoleAttributes::EReset: |
|
652 currentAttributes.iBackgroundColor = KDefaultBackgroundColor; |
|
653 break; |
|
654 case ConsoleAttributes::EUnchanged: |
|
655 // Do nothing. |
|
656 break; |
|
657 default: |
|
658 currentAttributes.iBackgroundColor = aBackgroundColor; |
|
659 break; |
|
660 } |
|
661 |
|
662 TRAPD(err, iFont->PrepareForegroundColorL(MapColor(currentAttributes.iAttributes, currentAttributes.iForegroundColor))); |
|
663 if (err == KErrNone) |
|
664 { |
|
665 iCurrentAttributes = currentAttributes; |
|
666 } |
|
667 |
|
668 return err; |
|
669 } |
|
670 |
|
671 void CConsoleControl::ViewMoved() |
|
672 { |
|
673 if (iViewWindow.iY < 0) iViewWindow.iY = 0; |
|
674 if (iViewWindow.iY + iSizeChars.iHeight > iBuffer.Count()) iViewWindow.iY = iBuffer.Count() - iSizeChars.iHeight; |
|
675 Window().Invalidate(); |
|
676 } |
|
677 |
|
678 void CConsoleControl::CursorWindowScrollDown() |
|
679 { |
|
680 TBool viewWindowMatchesCursorWindow = (iViewWindow.iY == iCursorWindow.iY); |
|
681 iCursorWindow.iY++; |
|
682 if (iCursorWindow.iY + iSizeChars.iHeight > iBuffer.Count()) |
|
683 { |
|
684 iCursorWindow.iY--; |
|
685 CConsoleLine* topLine = iBuffer[0]; |
|
686 iBuffer.Remove(0); |
|
687 topLine->Clear(); |
|
688 iBuffer.Append(topLine); |
|
689 |
|
690 // JB - Disabled the code below because it forces a full redraw of the window which seems |
|
691 // unnecessary, particularly now that this function trys to efficiently scroll using |
|
692 // RDrawableWindow::Scroll. Note though that I can't claim to fully understand this code, |
|
693 // so this may be a dumb thing to do. Original comment follows... |
|
694 // move this up so that the text in the view window moves up with the scrolling text. |
|
695 // ViewScrollUp(); |
|
696 } |
|
697 |
|
698 if (viewWindowMatchesCursorWindow) // keep them in sync if they were when we started |
|
699 { |
|
700 iViewWindow.iY = iCursorWindow.iY; |
|
701 } |
|
702 |
|
703 #ifndef FSHELL_WSERV2_SUPPORT |
|
704 // On wserv1 we can't use Scroll if we're showing the 5-way nav - it looks bad |
|
705 if (iDrawNavigator) |
|
706 { |
|
707 DrawDeferred(); |
|
708 } |
|
709 else |
|
710 #endif |
|
711 { |
|
712 // on wserv2, or wserv1 when the 5-way nav isn't displayed, we can use RWindow::Scroll for better performance (although, performance only seems to be a problem on wserv1 with a wide screen. On wserv2 probably just a DrawDeferred() would be sufficient) |
|
713 Invalidate5Way(); |
|
714 Window().Scroll(Rect(), TPoint(0, -(iFont->GlyphSize().iHeight))); |
|
715 Invalidate5Way(); |
|
716 TRect invalidRect(LineRect(TViewPosition(*this, 0, iSizeChars.iHeight - 1))); |
|
717 Window().Invalidate(invalidRect); |
|
718 } |
|
719 } |
|
720 |
|
721 EXPORT_C TPoint CConsoleControl::CursorPos() const |
|
722 { |
|
723 return iCursor.Position().iPoint; |
|
724 } |
|
725 |
|
726 EXPORT_C void CConsoleControl::SetCursorPosAbs(const TPoint &aPoint) |
|
727 { |
|
728 iCursor.SetPosAbs(TConsCursorPosition(*this, aPoint)); |
|
729 iCursor.Update(); |
|
730 } |
|
731 |
|
732 EXPORT_C void CConsoleControl::SetCursorPosRel(const TPoint &aPoint) |
|
733 { |
|
734 iCursor.SetPosRel(TConsCursorPosition(*this, aPoint)); |
|
735 iCursor.Update(); |
|
736 } |
|
737 |
|
738 EXPORT_C void CConsoleControl::SetCursorHeight(TInt aPercentage) |
|
739 { |
|
740 iCursor.SetHeight(aPercentage); |
|
741 iCursor.Update(); |
|
742 } |
|
743 |
|
744 EXPORT_C void CConsoleControl::SetTitle(const TDesC &aTitle) |
|
745 { |
|
746 if (iUi) |
|
747 { |
|
748 TRAP_IGNORE(iUi->ConsoleTitleChangedL(this, aTitle)); |
|
749 } |
|
750 } |
|
751 |
|
752 EXPORT_C void CConsoleControl::ClearScreen() |
|
753 { |
|
754 Window().Invalidate(); |
|
755 for (TInt y=0; y<iBuffer.Count(); ++y) |
|
756 { |
|
757 iBuffer[y]->Clear(); |
|
758 } |
|
759 iCursorWindow.iY = 0; |
|
760 iViewWindow.iY = 0; |
|
761 iCursor.SetPosAbs(TConsCursorPosition(*this, 0,0)); |
|
762 iCurrentAttributes = DefaultAttributes(); |
|
763 } |
|
764 |
|
765 EXPORT_C void CConsoleControl::ClearToEndOfLine() |
|
766 { |
|
767 GetLine(iCursor.Position())->ClearFrom(iCursor.Position()); |
|
768 Window().Invalidate(LineRect(iCursor.Position())); |
|
769 } |
|
770 |
|
771 EXPORT_C TSize CConsoleControl::ScreenSize() const |
|
772 { |
|
773 return iSizeChars; |
|
774 } |
|
775 |
|
776 EXPORT_C TKeyCode CConsoleControl::KeyCode() const |
|
777 { |
|
778 return (TKeyCode)iCurrentKey.iCode; |
|
779 } |
|
780 |
|
781 EXPORT_C TUint CConsoleControl::KeyModifiers() const |
|
782 { |
|
783 return iCurrentKey.iModifiers; |
|
784 } |
|
785 |
|
786 void CConsoleControl::SimulateKeyL(TButton aButton) |
|
787 { |
|
788 TKeyEvent key; |
|
789 key.iRepeats = 0; |
|
790 key.iModifiers = 0; |
|
791 switch (aButton) |
|
792 { |
|
793 case EUp: |
|
794 key.iCode = EKeyUpArrow; |
|
795 key.iScanCode = EStdKeyUpArrow; |
|
796 break; |
|
797 case EDown: |
|
798 key.iCode = EKeyDownArrow; |
|
799 key.iScanCode = EStdKeyDownArrow; |
|
800 break; |
|
801 case ELeft: |
|
802 key.iCode = EKeyLeftArrow; |
|
803 key.iScanCode = EStdKeyLeftArrow; |
|
804 break; |
|
805 case ERight: |
|
806 key.iCode = EKeyRightArrow; |
|
807 key.iScanCode = EStdKeyRightArrow; |
|
808 break; |
|
809 case ECenter: |
|
810 key.iCode = EKeyEnter; |
|
811 key.iScanCode = EStdKeyEnter; |
|
812 break; |
|
813 default: |
|
814 return; |
|
815 } |
|
816 iCoeEnv->SimulateKeyEventL(key, EEventKey); |
|
817 } |
|
818 |
|
819 EXPORT_C TBool CConsoleControl::FivewayNavIsDisplaying() const |
|
820 { |
|
821 return iButtonRects[ECenter].Width(); |
|
822 } |
|
823 |
|
824 EXPORT_C void CConsoleControl::SetDisplayFivewayNav(TBool aShow) |
|
825 { |
|
826 if (aShow) |
|
827 { |
|
828 TRect rect(Rect()); |
|
829 TInt shortLen = Min(rect.Width(), rect.Height()); // Look nicer in landscape |
|
830 TSize buttonSize(shortLen / 4, shortLen / 4); |
|
831 TRect center(TPoint(rect.Width()/2 - buttonSize.iWidth/2, rect.Height() - 2*buttonSize.iHeight), buttonSize); |
|
832 iButtonRects[ECenter] = center; |
|
833 iButtonRects[ECenter].Shrink(5, 5); |
|
834 iButtonRects[ELeft] = center; iButtonRects[ELeft].Move(-buttonSize.iWidth, 0); |
|
835 iButtonRects[ERight] = center; iButtonRects[ERight].Move(buttonSize.iWidth, 0); |
|
836 iButtonRects[EUp] = center; iButtonRects[EUp].Move(0, -buttonSize.iHeight); |
|
837 iButtonRects[EDown] = center; iButtonRects[EDown].Move(0, buttonSize.iHeight); |
|
838 iDrawNavigator = ETrue; |
|
839 } |
|
840 else |
|
841 { |
|
842 Mem::FillZ(iButtonRects, sizeof(iButtonRects)); |
|
843 } |
|
844 DrawDeferred(); |
|
845 } |
|
846 |
|
847 void CConsoleControl::ActivateL() |
|
848 { |
|
849 Window().SetBackgroundColor(KRgbWhite); |
|
850 CCoeControl::ActivateL(); |
|
851 } |
|
852 |
|
853 //______________________________________________________________________________ |
|
854 // Image loader thread |
|
855 // We use ICl to decode the font image. Despite ICL having the ability to create |
|
856 // a thread of it own to do the decoding, when we decode from a descriptor |
|
857 // (instead of a file), it still requires a AO RunL's in out thread to operate. |
|
858 // So, we have to create a new thread manually so that we can always load images |
|
859 // synchronously. |
|
860 |
|
861 class RImageDecodeThreadParams |
|
862 { |
|
863 public: |
|
864 RImageDecodeThreadParams(const TDesC& aFileName) |
|
865 : iMode(EDecodeFile), iFileName(aFileName), iData(KNullDesC8), iBitmapHandle(KNullHandle) {} |
|
866 RImageDecodeThreadParams(const TDesC8& aImageData) |
|
867 : iMode(EDecodeData), iFileName(KNullDesC), iData(aImageData), iBitmapHandle(KNullHandle) {} |
|
868 TInt Open() |
|
869 { |
|
870 TInt err = iBitmapReadySemaphore.CreateLocal(0); |
|
871 if (err==KErrNone) err = iThreadExitSemaphore.CreateLocal(0); |
|
872 if (err!=KErrNone) Close(); |
|
873 return err; |
|
874 } |
|
875 void Close() |
|
876 { |
|
877 iBitmapReadySemaphore.Close(); |
|
878 iThreadExitSemaphore.Close(); |
|
879 } |
|
880 public: |
|
881 enum |
|
882 { |
|
883 EDecodeFile, |
|
884 EDecodeData, |
|
885 } iMode; |
|
886 const TPtrC iFileName; |
|
887 const TPtrC8 iData; |
|
888 TFrameInfo iFrameInfo; |
|
889 TInt iBitmapHandle; |
|
890 RSemaphore iBitmapReadySemaphore; |
|
891 RSemaphore iThreadExitSemaphore; |
|
892 TInt iThreadError; |
|
893 }; |
|
894 |
|
895 class CImageDecodeWaiter : public CActive |
|
896 { |
|
897 public: |
|
898 CImageDecodeWaiter(TInt aPriority) |
|
899 : CActive(aPriority) |
|
900 { |
|
901 CActiveScheduler::Add(this); |
|
902 } |
|
903 void Start(CImageDecoder* aDecoder, CFbsBitmap* aBitmap) |
|
904 { |
|
905 TRequestStatus* stat = &iStatus; |
|
906 aDecoder->Convert(stat, *aBitmap); |
|
907 SetActive(); |
|
908 CActiveScheduler::Start(); |
|
909 } |
|
910 virtual void RunL() |
|
911 { |
|
912 iCompletionErr = iStatus.Int(); |
|
913 CActiveScheduler::Stop(); |
|
914 } |
|
915 virtual void DoCancel() {} |
|
916 public: |
|
917 TInt iCompletionErr; |
|
918 }; |
|
919 |
|
920 void ImageDecodeThreadL(RImageDecodeThreadParams& aParams) |
|
921 { |
|
922 User::LeaveIfError(RFbsSession::Connect()); |
|
923 |
|
924 CActiveScheduler* as = new(ELeave)CActiveScheduler; |
|
925 CActiveScheduler::Install(as); |
|
926 CleanupStack::PushL(as); |
|
927 |
|
928 RFs fs; |
|
929 User::LeaveIfError(fs.Connect()); |
|
930 CleanupClosePushL(fs); |
|
931 User::LeaveIfError(fs.ShareAuto()); |
|
932 |
|
933 CImageDecoder* dec = NULL; |
|
934 switch (aParams.iMode) |
|
935 { |
|
936 case RImageDecodeThreadParams::EDecodeFile: |
|
937 dec = CImageDecoder::FileNewL(fs, aParams.iFileName); |
|
938 break; |
|
939 case RImageDecodeThreadParams::EDecodeData: |
|
940 dec = CImageDecoder::DataNewL(fs, aParams.iData); |
|
941 break; |
|
942 } |
|
943 CleanupStack::PushL(dec); |
|
944 |
|
945 aParams.iFrameInfo = dec->FrameInfo(); |
|
946 CFbsBitmap* bmp = new(ELeave)CFbsBitmap; |
|
947 CleanupStack::PushL(bmp); |
|
948 User::LeaveIfError(bmp->Create(aParams.iFrameInfo.iOverallSizeInPixels, aParams.iFrameInfo.iFrameDisplayMode)); |
|
949 |
|
950 |
|
951 CImageDecodeWaiter* waiter = new(ELeave)CImageDecodeWaiter(CActive::EPriorityStandard); |
|
952 CleanupStack::PushL(waiter); |
|
953 |
|
954 waiter->Start(dec, bmp); |
|
955 User::LeaveIfError(waiter->iCompletionErr); |
|
956 |
|
957 aParams.iBitmapHandle = bmp->Handle(); |
|
958 aParams.iThreadError = KErrNone; |
|
959 aParams.iBitmapReadySemaphore.Signal(); |
|
960 aParams.iThreadExitSemaphore.Wait(); |
|
961 |
|
962 CleanupStack::PopAndDestroy(5, as); // as, fs, dec, bmp, waiter |
|
963 } |
|
964 |
|
965 TInt ImageDecodeThead(TAny* aParams) |
|
966 { |
|
967 User::SetCritical(User::EProcessCritical); |
|
968 __UHEAP_MARK; |
|
969 RImageDecodeThreadParams* params = (RImageDecodeThreadParams*)aParams; |
|
970 |
|
971 CTrapCleanup* cleanup = CTrapCleanup::New(); // get clean-up stack |
|
972 if (!cleanup) return KErrNoMemory; |
|
973 TRAPD(err, ImageDecodeThreadL(*params)); |
|
974 params->iThreadError = err; |
|
975 if (err!=KErrNone) |
|
976 { |
|
977 params->iBitmapReadySemaphore.Signal(); |
|
978 } |
|
979 |
|
980 delete cleanup; |
|
981 REComSession::FinalClose(); |
|
982 RFbsSession::Disconnect(); |
|
983 __UHEAP_MARKEND; |
|
984 User::SetCritical(User::ENotCritical); |
|
985 return err; |
|
986 } |
|
987 |
|
988 //______________________________________________________________________________ |
|
989 // CConsoleFont |
|
990 EXPORT_C CConsoleFont* CConsoleFont::NewL(const TDesC& aFontFile) |
|
991 { |
|
992 CConsoleFont* self = new(ELeave)CConsoleFont; |
|
993 CleanupStack::PushL(self); |
|
994 self->ConstructL(aFontFile); |
|
995 CleanupStack::Pop(self); |
|
996 return self; |
|
997 } |
|
998 |
|
999 EXPORT_C CConsoleFont* CConsoleFont::NewL(const TDesC8& aEncodedFontImage) |
|
1000 { |
|
1001 CConsoleFont* self = new(ELeave)CConsoleFont; |
|
1002 CleanupStack::PushL(self); |
|
1003 self->ConstructL(aEncodedFontImage); |
|
1004 CleanupStack::Pop(self); |
|
1005 return self; |
|
1006 } |
|
1007 |
|
1008 EXPORT_C CConsoleFont::~CConsoleFont() |
|
1009 { |
|
1010 for (TInt i = 0; i < KNumGlyphs; ++i) |
|
1011 { |
|
1012 delete iChars[i]; |
|
1013 } |
|
1014 for (TInt i = 0; i < KNumColors; ++i) |
|
1015 { |
|
1016 delete iColors[i]; |
|
1017 } |
|
1018 } |
|
1019 |
|
1020 EXPORT_C TSize CConsoleFont::GlyphSize() const |
|
1021 { |
|
1022 return iGlyphRect.Size(); |
|
1023 } |
|
1024 |
|
1025 |
|
1026 EXPORT_C void CConsoleFont::DrawChar(TChar aChar, CBitmapContext& aDrawTo, TPoint aPosPixels, TRgb aColor) |
|
1027 { |
|
1028 // Note, this method assumes that the glyph's background has already been set to the appropriate color. |
|
1029 |
|
1030 if ((aChar < KFontBitmapFirstCharCode) || (aChar > KFontBitmapLastCharCode)) |
|
1031 { |
|
1032 aChar = KFontBitmapLastCharCode; |
|
1033 } |
|
1034 |
|
1035 aDrawTo.BitBltMasked(aPosPixels, ForegroundBitmap(aColor), iGlyphRect, iChars[(TInt)aChar - KFontBitmapFirstCharCode], ETrue); |
|
1036 } |
|
1037 |
|
1038 CConsoleFont::CConsoleFont() |
|
1039 { |
|
1040 } |
|
1041 |
|
1042 void CConsoleFont::ConstructL(const TDesC& aFontFile) |
|
1043 { |
|
1044 RImageDecodeThreadParams decodeParams(aFontFile); |
|
1045 ConstructL(decodeParams); |
|
1046 } |
|
1047 |
|
1048 void CConsoleFont::ConstructL(const TDesC8& aEncodedFontImage) |
|
1049 { |
|
1050 RImageDecodeThreadParams decodeParams(aEncodedFontImage); |
|
1051 ConstructL(decodeParams); |
|
1052 } |
|
1053 |
|
1054 _LIT(KImageDecodeThreadNameFmt, "ImageDecodeThread%08x"); |
|
1055 |
|
1056 void CConsoleFont::ConstructL(RImageDecodeThreadParams& aDecodeParams) |
|
1057 { |
|
1058 User::LeaveIfError(aDecodeParams.Open()); |
|
1059 CleanupClosePushL(aDecodeParams); |
|
1060 RThread decodeThread; |
|
1061 CleanupClosePushL(decodeThread); |
|
1062 // kick off the sub thread doing the decoding |
|
1063 TInt err; |
|
1064 TInt seq = 0; |
|
1065 do |
|
1066 { |
|
1067 TBuf<0x20> threadName; |
|
1068 threadName.AppendFormat(KImageDecodeThreadNameFmt, seq); |
|
1069 err = decodeThread.Create(threadName, ImageDecodeThead, KDefaultStackSize, 0x1000, 0x200000, &aDecodeParams); |
|
1070 seq++; |
|
1071 } while (err==KErrAlreadyExists); |
|
1072 User::LeaveIfError(err); |
|
1073 decodeThread.Resume(); |
|
1074 |
|
1075 TRequestStatus threadExit; |
|
1076 decodeThread.Logon(threadExit); |
|
1077 |
|
1078 CleanupWaitForRequestPushL(threadExit); // things will probably go wrong if we leave on this line |
|
1079 CleanupSignalSemaphorePushL(aDecodeParams.iThreadExitSemaphore); |
|
1080 |
|
1081 /* |
|
1082 Now, on the cleanup stack we have: |
|
1083 1. iThreadExitSemaphore.Signal() |
|
1084 2. WaitForRequest(threadExit) |
|
1085 3. decodeThread |
|
1086 4. aDecodeParams |
|
1087 |
|
1088 So, if we leave now: |
|
1089 1. We will signal the sub thread to exit |
|
1090 2. We will then wait for the sub thread to exit |
|
1091 3. close the sub thread handle |
|
1092 4. close aDecodeParams, which will destroy the semaphores |
|
1093 |
|
1094 Note, it's important that we wait for the thread to exit before the cleanup stack |
|
1095 if fully unwound, as if we destroy the semaphores before the sub thread has exitted, |
|
1096 then it will panic with KERN-EXEC 0. |
|
1097 */ |
|
1098 |
|
1099 // wait for it to decode the bitmap (or die) |
|
1100 aDecodeParams.iBitmapReadySemaphore.Wait(); |
|
1101 User::LeaveIfError(aDecodeParams.iThreadError); // we will leave here if there was an error in the subthread |
|
1102 |
|
1103 // process decoded image |
|
1104 TSize bmpSize = aDecodeParams.iFrameInfo.iOverallSizeInPixels; |
|
1105 if (bmpSize.iWidth % KFontBitmapWidthChars) User::Leave(KErrCorrupt);// better error code / panic? |
|
1106 if (bmpSize.iHeight % KFontBitmapHeightChars) User::Leave(KErrCorrupt);// better error code / panic? |
|
1107 iGlyphRect = TRect(TPoint(0, 0), TSize(bmpSize.iWidth / KFontBitmapWidthChars, bmpSize.iHeight / KFontBitmapHeightChars)); |
|
1108 |
|
1109 CFbsBitmap* allChars = new(ELeave)CFbsBitmap(); |
|
1110 CleanupStack::PushL(allChars); |
|
1111 User::LeaveIfError(allChars->Duplicate(aDecodeParams.iBitmapHandle)); |
|
1112 |
|
1113 for (TInt i = 0; i < KNumGlyphs; ++i) |
|
1114 { |
|
1115 iChars[i] = new(ELeave)CFbsBitmap; |
|
1116 User::LeaveIfError(iChars[i]->Create(iGlyphRect.Size(), EGray2)); |
|
1117 |
|
1118 CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(iChars[i]); |
|
1119 CleanupStack::PushL(bitmapDevice); |
|
1120 |
|
1121 CBitmapContext* bitmapContext; |
|
1122 User::LeaveIfError(bitmapDevice->CreateBitmapContext(bitmapContext)); |
|
1123 CleanupStack::PushL(bitmapContext); |
|
1124 |
|
1125 TPoint charPos(i % KFontBitmapWidthChars, i / KFontBitmapWidthChars); |
|
1126 TPoint pixelPos(charPos.iX * iGlyphRect.Size().iWidth, charPos.iY * iGlyphRect.Size().iHeight); |
|
1127 TRect charRect(pixelPos, iGlyphRect.Size()); |
|
1128 bitmapContext->BitBlt(TPoint(0, 0), allChars, charRect); |
|
1129 |
|
1130 CleanupStack::PopAndDestroy(2, bitmapDevice); |
|
1131 } |
|
1132 |
|
1133 // this will clean everything up - see above comment. |
|
1134 CleanupStack::PopAndDestroy(5, &aDecodeParams); // decodeThread, aDecodeParams |
|
1135 |
|
1136 PrepareForegroundColorL(KDefaultForegroundColor); |
|
1137 } |
|
1138 |
|
1139 void CConsoleFont::PrepareForegroundColorL(TRgb aColor) |
|
1140 { |
|
1141 CFbsBitmap* bitmap = ForegroundBitmap(aColor); |
|
1142 if (bitmap == NULL) |
|
1143 { |
|
1144 bitmap = new(ELeave)CFbsBitmap; |
|
1145 CleanupStack::PushL(bitmap); |
|
1146 User::LeaveIfError(bitmap->Create(iGlyphRect.Size(), EColor16)); |
|
1147 CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(bitmap); |
|
1148 CleanupStack::PushL(bitmapDevice); |
|
1149 CBitmapContext* bitmapContext; |
|
1150 User::LeaveIfError(bitmapDevice->CreateBitmapContext(bitmapContext)); |
|
1151 CleanupStack::PushL(bitmapContext); |
|
1152 bitmapContext->SetBrushColor(aColor); |
|
1153 bitmapContext->SetPenStyle(CGraphicsContext::ENullPen); |
|
1154 bitmapContext->SetBrushStyle(CGraphicsContext::ESolidBrush); |
|
1155 bitmapContext->DrawRect(iGlyphRect); |
|
1156 CleanupStack::PopAndDestroy(2, bitmapDevice); |
|
1157 CleanupStack::Pop(bitmap); |
|
1158 iColors[aColor.Color16()] = bitmap; |
|
1159 } |
|
1160 } |
|
1161 |
|
1162 CFbsBitmap* CConsoleFont::ForegroundBitmap(TRgb aColor) |
|
1163 { |
|
1164 return iColors[aColor.Color16()]; |
|
1165 } |
|
1166 |
|
1167 //______________________________________________________________________________ |
|
1168 // CConsoleLine |
|
1169 CConsoleLine* CConsoleLine::NewL(CConsoleControl& aControl, const CConsoleFont& aFont, TInt aWidth) |
|
1170 { |
|
1171 CConsoleLine* self = new(ELeave)CConsoleLine(aControl, aFont); |
|
1172 CleanupStack::PushL(self); |
|
1173 self->ConstructL(aWidth); |
|
1174 CleanupStack::Pop(self); |
|
1175 return self; |
|
1176 } |
|
1177 |
|
1178 CConsoleLine::~CConsoleLine() |
|
1179 { |
|
1180 iText.Close(); |
|
1181 iAttributeMap.Close(); |
|
1182 } |
|
1183 |
|
1184 void CConsoleLine::SetWidthL(TInt aNewWidth) |
|
1185 { |
|
1186 if (aNewWidth != iWidth) |
|
1187 { |
|
1188 RBuf8 newText; |
|
1189 newText.CreateL(aNewWidth); |
|
1190 newText.Copy(iText.Left(aNewWidth)); |
|
1191 newText.Swap(iText); |
|
1192 newText.Close(); |
|
1193 iWidth = aNewWidth; |
|
1194 iAttributeMap.RemoveFrom(aNewWidth); |
|
1195 } |
|
1196 } |
|
1197 |
|
1198 void CConsoleLine::SetL(TInt aIndex, TUint8 aChar, const ConsoleAttributes::TAttributes& aAttributes) |
|
1199 { |
|
1200 __ASSERT_ALWAYS((aIndex < iWidth)&&(aIndex>=0), User::Invariant()); |
|
1201 iAttributeMap.AddL(aIndex, iWidth, aAttributes); |
|
1202 if (aIndex > iText.Length()) |
|
1203 { |
|
1204 TInt oldLen = iText.Length(); |
|
1205 iText.SetLength(aIndex); |
|
1206 iText.MidTPtr(oldLen).Fill(' '); |
|
1207 iText.Append(aChar); |
|
1208 } |
|
1209 else if (aIndex == iText.Length()) |
|
1210 { |
|
1211 iText.Append(aChar); |
|
1212 } |
|
1213 else |
|
1214 { |
|
1215 iText[aIndex] = aChar; |
|
1216 } |
|
1217 } |
|
1218 |
|
1219 void CConsoleLine::Clear() |
|
1220 { |
|
1221 iAttributeMap.Reset(); |
|
1222 iText.Zero(); |
|
1223 } |
|
1224 |
|
1225 void CConsoleLine::ClearFrom(TBufferPosition aPos) |
|
1226 { |
|
1227 TInt pos = Min(aPos.iPoint.iX, iText.Length()); |
|
1228 iText.SetLength(pos); |
|
1229 iAttributeMap.RemoveFrom(pos); |
|
1230 } |
|
1231 |
|
1232 void CConsoleLine::Draw(CBitmapContext& aDrawTo, TViewPosition aViewPosition) const |
|
1233 { |
|
1234 const TSize glyphSize(iFont.GlyphSize()); |
|
1235 |
|
1236 TScreenPosition screenPos(aViewPosition); |
|
1237 TRect rectToClear(screenPos.iPoint, TScreenPosition(aViewPosition.iConsole, 0, (aViewPosition.iPoint.iY + 1) * glyphSize.iHeight).iPoint); |
|
1238 |
|
1239 const TInt numAttributeBlocks = iAttributeMap.NumberOfBlocks(); |
|
1240 for (TInt i = 0; i < numAttributeBlocks; ++i) |
|
1241 { |
|
1242 TInt startXPos = 0; |
|
1243 TInt endXPos = 0; |
|
1244 ConsoleAttributes::TAttributes attributes(ConsoleAttributes::ENone); |
|
1245 iAttributeMap.GetBlock(i, iWidth, startXPos, endXPos, attributes); |
|
1246 |
|
1247 // Draw the background in the appropriate color in one hit. |
|
1248 rectToClear.iTl.iX = screenPos.iPoint.iX + (startXPos * glyphSize.iWidth); |
|
1249 rectToClear.iBr.iX = screenPos.iPoint.iX + (endXPos * glyphSize.iWidth); |
|
1250 TRgb backgroundColor = MapColor(attributes.iAttributes, attributes.iBackgroundColor); |
|
1251 aDrawTo.SetBrushColor(backgroundColor); |
|
1252 aDrawTo.Clear(rectToClear); |
|
1253 |
|
1254 // Check if we're blinking. |
|
1255 TRgb foregroundColor = MapColor(attributes.iAttributes, attributes.iForegroundColor); |
|
1256 if ((attributes.iAttributes & ConsoleAttributes::EBlink) && iBlinkOn) |
|
1257 { |
|
1258 foregroundColor = backgroundColor; |
|
1259 } |
|
1260 |
|
1261 // Draw any non-white-space characters in the appropriate foreground color. |
|
1262 for (TInt i = startXPos; i < endXPos; ++i) |
|
1263 { |
|
1264 TUint16 c = At(i); |
|
1265 if (c != ' ') |
|
1266 { |
|
1267 const_cast<CConsoleFont&>(iFont).DrawChar(c, aDrawTo, TPoint(screenPos.iPoint.iX + (i * glyphSize.iWidth), screenPos.iPoint.iY), foregroundColor); |
|
1268 } |
|
1269 if (attributes.iAttributes & ConsoleAttributes::EUnderscore) |
|
1270 { |
|
1271 const_cast<CConsoleFont&>(iFont).DrawChar('_', aDrawTo, TPoint(screenPos.iPoint.iX + (i * glyphSize.iWidth), screenPos.iPoint.iY), foregroundColor); |
|
1272 } |
|
1273 } |
|
1274 |
|
1275 if (attributes.iAttributes & ConsoleAttributes::EBlink) |
|
1276 { |
|
1277 iControl.StartBlinking(); |
|
1278 } |
|
1279 } |
|
1280 } |
|
1281 |
|
1282 TBool CConsoleLine::NeedToBlink(TBool aBlinkOn) |
|
1283 { |
|
1284 TBool needToBlink(EFalse); |
|
1285 const TInt numAttributeBlocks = iAttributeMap.NumberOfBlocks(); |
|
1286 for (TInt i = 0; i < numAttributeBlocks; ++i) |
|
1287 { |
|
1288 TInt startXPos = 0; |
|
1289 TInt endXPos = 0; |
|
1290 ConsoleAttributes::TAttributes attributes(ConsoleAttributes::ENone); |
|
1291 iAttributeMap.GetBlock(i, iWidth, startXPos, endXPos, attributes); |
|
1292 if (attributes.iAttributes & ConsoleAttributes::EBlink) |
|
1293 { |
|
1294 needToBlink = ETrue; |
|
1295 iBlinkOn = aBlinkOn; |
|
1296 break; |
|
1297 } |
|
1298 } |
|
1299 return needToBlink; |
|
1300 } |
|
1301 |
|
1302 TUint16 CConsoleLine::At(TInt aPos) const |
|
1303 { |
|
1304 __ASSERT_ALWAYS((aPos < iWidth)&&(aPos>=0), User::Invariant()); |
|
1305 if (aPos < iText.Length()) |
|
1306 { |
|
1307 return iText[aPos]; |
|
1308 } |
|
1309 else |
|
1310 { |
|
1311 return ' '; |
|
1312 } |
|
1313 } |
|
1314 |
|
1315 CConsoleLine::CConsoleLine(CConsoleControl& aControl, const CConsoleFont& aFont) |
|
1316 : iControl(aControl), iFont(aFont) |
|
1317 { |
|
1318 } |
|
1319 |
|
1320 void CConsoleLine::ConstructL(TInt aWidth) |
|
1321 { |
|
1322 iText.CreateL(aWidth); |
|
1323 iWidth = aWidth; |
|
1324 } |
|
1325 |
|
1326 //______________________________________________________________________________ |
|
1327 // TConsoleCursor |
|
1328 TConsoleCursor::TConsoleCursor(CConsoleControl& aOwner) |
|
1329 : iOwner(aOwner) |
|
1330 { |
|
1331 iTextCursor.iType = TTextCursor::ETypeRectangle; |
|
1332 iTextCursor.iAscent = 0; |
|
1333 iTextCursor.iColor = KRgbWhite; |
|
1334 } |
|
1335 |
|
1336 void TConsoleCursor::SetFont(const CConsoleFont& aFont) |
|
1337 { |
|
1338 iGlyphSize = aFont.GlyphSize(); |
|
1339 iTextCursor.iWidth = iGlyphSize.iWidth; |
|
1340 } |
|
1341 |
|
1342 TConsCursorPosition TConsoleCursor::Position() const |
|
1343 { |
|
1344 return TConsCursorPosition(iOwner, iPosition); |
|
1345 } |
|
1346 |
|
1347 void TConsoleCursor::SetPosAbs(TConsCursorPosition aPos) |
|
1348 { |
|
1349 iPosition = aPos.iPoint; |
|
1350 BoundsCheck(); |
|
1351 } |
|
1352 |
|
1353 void TConsoleCursor::SetPosRel(TConsCursorPosition aPos) |
|
1354 { |
|
1355 iPosition += aPos.iPoint; |
|
1356 BoundsCheck(); |
|
1357 } |
|
1358 |
|
1359 void TConsoleCursor::SetHeight(TInt aPercentage) |
|
1360 { |
|
1361 aPercentage = Max(0, Min(100, aPercentage)); |
|
1362 TReal height = ((TReal)iGlyphSize.iHeight * (TReal)aPercentage) / 100.0; |
|
1363 TReal roundedHeight; |
|
1364 Math::Round(roundedHeight, height, 0); |
|
1365 iTextCursor.iHeight = (TInt)roundedHeight; |
|
1366 // make sure the cursor is always visible if the percentage is non-zero. |
|
1367 if ((iTextCursor.iHeight==0) && (aPercentage!=0)) iTextCursor.iHeight = 1; |
|
1368 iTextCursor.iAscent = 0; |
|
1369 iTextCursorOffset = iGlyphSize.iHeight - iTextCursor.iHeight; |
|
1370 } |
|
1371 |
|
1372 void TConsoleCursor::Update() |
|
1373 { |
|
1374 if (iOwner.IsFocused() && !iOwner.IsNonFocusing()) |
|
1375 { |
|
1376 TViewPosition viewPos = Position(); |
|
1377 TPoint cursorPosPixels; |
|
1378 cursorPosPixels.iX = viewPos.iPoint.iX * iGlyphSize.iWidth; |
|
1379 cursorPosPixels.iY = ((viewPos.iPoint.iY) * iGlyphSize.iHeight) + iTextCursorOffset; |
|
1380 /*if (iOwner.Rect().Contains(cursorPosPixels)) |
|
1381 {*/ |
|
1382 if (iOwner.DrawableWindow()) |
|
1383 { |
|
1384 CCoeEnv::Static()->RootWin().SetTextCursor(*iOwner.DrawableWindow(), cursorPosPixels, iTextCursor); |
|
1385 } |
|
1386 /* } |
|
1387 else |
|
1388 { |
|
1389 Hide(); |
|
1390 }*/ |
|
1391 } |
|
1392 } |
|
1393 |
|
1394 void TConsoleCursor::Hide() |
|
1395 { |
|
1396 CCoeEnv::Static()->RootWin().CancelTextCursor(); |
|
1397 } |
|
1398 |
|
1399 void TConsoleCursor::BoundsCheck() |
|
1400 { |
|
1401 iPosition.iX = Max(0, iPosition.iX); |
|
1402 iPosition.iY = Max(0, iPosition.iY); |
|
1403 iPosition.iX = Min(iOwner.ScreenSize().iWidth-1, iPosition.iX); |
|
1404 iPosition.iY = Min(iOwner.ScreenSize().iHeight-1, iPosition.iY); |
|
1405 } |
|
1406 |
|
1407 void TConsoleCursor::operator++(int) |
|
1408 { |
|
1409 (*this)+=1; |
|
1410 } |
|
1411 |
|
1412 void TConsoleCursor::operator--(int) |
|
1413 { |
|
1414 (*this)-=1; |
|
1415 } |
|
1416 |
|
1417 void TConsoleCursor::operator+=(TUint aHowMuch) |
|
1418 { |
|
1419 TSize consSize(iOwner.ScreenSize()); |
|
1420 while (aHowMuch) |
|
1421 { |
|
1422 TInt len = Min(consSize.iWidth - iPosition.iX, aHowMuch); |
|
1423 iPosition.iX += len; |
|
1424 aHowMuch -= len; |
|
1425 |
|
1426 if (iPosition.iX == consSize.iWidth) |
|
1427 { |
|
1428 Down(); |
|
1429 iPosition.iX = 0; |
|
1430 } |
|
1431 } |
|
1432 } |
|
1433 |
|
1434 void TConsoleCursor::operator-=(TUint aHowMuch) |
|
1435 { |
|
1436 TSize consSize(iOwner.ScreenSize()); |
|
1437 while (aHowMuch) |
|
1438 { |
|
1439 if (iPosition.iX == 0) |
|
1440 { |
|
1441 Up(); |
|
1442 iPosition.iX = consSize.iWidth; |
|
1443 } |
|
1444 |
|
1445 TInt len = Min(iPosition.iX, aHowMuch); |
|
1446 iPosition.iX -= len; |
|
1447 aHowMuch -= len; |
|
1448 } |
|
1449 |
|
1450 } |
|
1451 |
|
1452 void TConsoleCursor::Down() |
|
1453 { |
|
1454 iPosition.iY++; |
|
1455 if (iPosition.iY >= iOwner.ScreenSize().iHeight) |
|
1456 { |
|
1457 iPosition.iY--; |
|
1458 iOwner.CursorWindowScrollDown(); |
|
1459 } |
|
1460 } |
|
1461 |
|
1462 void TConsoleCursor::Up() |
|
1463 { |
|
1464 iPosition.iY--; |
|
1465 BoundsCheck(); |
|
1466 } |
|
1467 |
|
1468 //______________________________________________________________________________ |
|
1469 // CGuiConsole |
|
1470 EXPORT_C CGuiConsole::CGuiConsole(CConsoleControl& aControl) |
|
1471 : iControl(aControl), iRefCount(1) |
|
1472 { |
|
1473 } |
|
1474 |
|
1475 EXPORT_C CConsoleControl& CGuiConsole::Control() |
|
1476 { |
|
1477 return iControl; |
|
1478 } |
|
1479 |
|
1480 EXPORT_C TInt CGuiConsole::Create(const TDesC &aTitle, TSize) |
|
1481 { |
|
1482 iControl.SetTitle(aTitle); |
|
1483 return KErrNone; |
|
1484 } |
|
1485 |
|
1486 EXPORT_C void CGuiConsole::Read(TRequestStatus &aStatus) |
|
1487 { |
|
1488 if (iReadStatus || iReader) |
|
1489 { |
|
1490 TRequestStatus* stat = &aStatus; |
|
1491 User::RequestComplete(stat, KErrInUse); |
|
1492 } |
|
1493 else |
|
1494 { |
|
1495 iReadStatus = &aStatus; |
|
1496 iControl.Read(*this); |
|
1497 } |
|
1498 } |
|
1499 |
|
1500 EXPORT_C void CGuiConsole::ReadCancel() |
|
1501 { |
|
1502 if (iReadStatus) |
|
1503 { |
|
1504 User::RequestComplete(iReadStatus, KErrCancel); |
|
1505 iControl.ReadCancel(); |
|
1506 } |
|
1507 else if (iReader) |
|
1508 { |
|
1509 iReader->ReadComplete(KErrCancel); |
|
1510 iReader = NULL; |
|
1511 iControl.ReadCancel(); |
|
1512 } |
|
1513 } |
|
1514 |
|
1515 EXPORT_C void CGuiConsole::Write(const TDesC &aDes) |
|
1516 { |
|
1517 iControl.Write(aDes); |
|
1518 } |
|
1519 |
|
1520 EXPORT_C TPoint CGuiConsole::CursorPos() const |
|
1521 { |
|
1522 return iControl.CursorPos(); |
|
1523 } |
|
1524 |
|
1525 EXPORT_C void CGuiConsole::SetCursorPosAbs(const TPoint &aPoint) |
|
1526 { |
|
1527 iControl.SetCursorPosAbs(aPoint); |
|
1528 } |
|
1529 |
|
1530 EXPORT_C void CGuiConsole::SetCursorPosRel(const TPoint &aPoint) |
|
1531 { |
|
1532 iControl.SetCursorPosRel(aPoint); |
|
1533 } |
|
1534 |
|
1535 EXPORT_C void CGuiConsole::SetCursorHeight(TInt aPercentage) |
|
1536 { |
|
1537 iControl.SetCursorHeight(aPercentage); |
|
1538 } |
|
1539 |
|
1540 EXPORT_C void CGuiConsole::SetTitle(const TDesC &aTitle) |
|
1541 { |
|
1542 iControl.SetTitle(aTitle); |
|
1543 } |
|
1544 |
|
1545 EXPORT_C void CGuiConsole::ClearScreen() |
|
1546 { |
|
1547 iControl.ClearScreen(); |
|
1548 } |
|
1549 |
|
1550 EXPORT_C void CGuiConsole::ClearToEndOfLine() |
|
1551 { |
|
1552 iControl.ClearToEndOfLine(); |
|
1553 } |
|
1554 |
|
1555 EXPORT_C TSize CGuiConsole::ScreenSize() const |
|
1556 { |
|
1557 return iControl.ScreenSize(); |
|
1558 } |
|
1559 |
|
1560 |
|
1561 EXPORT_C TKeyCode CGuiConsole::KeyCode() const |
|
1562 { |
|
1563 return iControl.KeyCode(); |
|
1564 } |
|
1565 |
|
1566 |
|
1567 EXPORT_C TUint CGuiConsole::KeyModifiers() const |
|
1568 { |
|
1569 return iControl.KeyModifiers(); |
|
1570 } |
|
1571 |
|
1572 EXPORT_C TInt CGuiConsole::Extension_(TUint aExtensionId, TAny*&, TAny* a1) |
|
1573 { |
|
1574 if (aExtensionId == ConsoleAttributes::KSetConsoleAttributesExtension) |
|
1575 { |
|
1576 ConsoleAttributes::TAttributes* attributes = (ConsoleAttributes::TAttributes*)a1; |
|
1577 return iControl.SetAttributes(attributes->iAttributes, attributes->iForegroundColor, attributes->iBackgroundColor); |
|
1578 } |
|
1579 return KErrNotSupported; |
|
1580 } |
|
1581 |
|
1582 void CGuiConsole::ReadComplete(TInt aStatus) |
|
1583 { |
|
1584 if (iReadStatus) |
|
1585 { |
|
1586 User::RequestComplete(iReadStatus, aStatus); |
|
1587 } |
|
1588 if (iReader) |
|
1589 { |
|
1590 CConsoleProxySession* reader = iReader; |
|
1591 iReader = NULL; |
|
1592 reader->ReadComplete(aStatus); |
|
1593 } |
|
1594 } |
|
1595 |
|
1596 void CGuiConsole::Open() |
|
1597 { |
|
1598 ++iRefCount; |
|
1599 } |
|
1600 |
|
1601 void CGuiConsole::Close() |
|
1602 { |
|
1603 --iRefCount; |
|
1604 if (iRefCount==0) |
|
1605 { |
|
1606 delete this; |
|
1607 } |
|
1608 } |
|
1609 |
|
1610 CConsoleBase* CGuiConsole::Console() |
|
1611 { |
|
1612 return this; |
|
1613 } |
|
1614 |
|
1615 void CGuiConsole::Read(CConsoleProxySession& aSession) |
|
1616 { |
|
1617 if (iReader || iReadStatus) |
|
1618 { |
|
1619 aSession.ReadComplete(KErrInUse); |
|
1620 } |
|
1621 else |
|
1622 { |
|
1623 iReader = &aSession; |
|
1624 iControl.Read(*this); |
|
1625 } |
|
1626 } |
|
1627 |
|
1628 CGuiConsole::~CGuiConsole() |
|
1629 { |
|
1630 iControl.Closed(); |
|
1631 } |
|
1632 |
|
1633 //______________________________________________________________________________ |
|
1634 // TBufferPosition |
|
1635 TBufferPosition::TBufferPosition(const CConsoleControl& aConsole, TPoint aPosition) |
|
1636 : iConsole(aConsole), iPoint(aPosition) |
|
1637 { |
|
1638 } |
|
1639 |
|
1640 TBufferPosition::TBufferPosition(const CConsoleControl& aConsole, TInt aX, TInt aY) |
|
1641 : iConsole(aConsole), iPoint(aX, aY) |
|
1642 { |
|
1643 } |
|
1644 |
|
1645 TBufferPosition::TBufferPosition(const TConsCursorPosition& aCursorPosition) |
|
1646 : iConsole(aCursorPosition.iConsole) |
|
1647 , iPoint(aCursorPosition.iPoint + aCursorPosition.iConsole.CursorWindowPosition()) |
|
1648 { |
|
1649 } |
|
1650 |
|
1651 TBufferPosition::TBufferPosition(const TViewPosition& aViewPosition) |
|
1652 : iConsole(aViewPosition.iConsole) |
|
1653 , iPoint(aViewPosition.iPoint + aViewPosition.iConsole.ViewPosition()) |
|
1654 { |
|
1655 } |
|
1656 |
|
1657 |
|
1658 |
|
1659 //______________________________________________________________________________ |
|
1660 // TConsCursorPosition |
|
1661 TConsCursorPosition::TConsCursorPosition(const CConsoleControl& aConsole, TPoint aPosition) |
|
1662 : iConsole(aConsole), iPoint(aPosition) |
|
1663 { |
|
1664 } |
|
1665 |
|
1666 TConsCursorPosition::TConsCursorPosition(const CConsoleControl& aConsole, TInt aX, TInt aY) |
|
1667 : iConsole(aConsole), iPoint(aX, aY) |
|
1668 { |
|
1669 } |
|
1670 |
|
1671 TConsCursorPosition::TConsCursorPosition(const TBufferPosition& aBufferPosition) |
|
1672 : iConsole(aBufferPosition.iConsole) |
|
1673 , iPoint(aBufferPosition.iPoint - aBufferPosition.iConsole.CursorWindowPosition()) |
|
1674 { |
|
1675 } |
|
1676 |
|
1677 TConsCursorPosition::TConsCursorPosition(const TViewPosition& aViewPosition) |
|
1678 : iConsole(aViewPosition.iConsole) |
|
1679 , iPoint(aViewPosition.iPoint + aViewPosition.iConsole.ViewPosition() - aViewPosition.iConsole.CursorWindowPosition()) |
|
1680 { |
|
1681 } |
|
1682 |
|
1683 |
|
1684 |
|
1685 //______________________________________________________________________________ |
|
1686 // TViewPosition |
|
1687 TViewPosition::TViewPosition(const CConsoleControl& aConsole, TPoint aPosition) |
|
1688 : iConsole(aConsole), iPoint(aPosition) |
|
1689 { |
|
1690 } |
|
1691 |
|
1692 TViewPosition::TViewPosition(const CConsoleControl& aConsole, TInt aX, TInt aY) |
|
1693 : iConsole(aConsole), iPoint(aX, aY) |
|
1694 { |
|
1695 } |
|
1696 |
|
1697 TViewPosition::TViewPosition(const TConsCursorPosition& aCursorPosition) |
|
1698 : iConsole(aCursorPosition.iConsole) |
|
1699 , iPoint(aCursorPosition.iPoint + aCursorPosition.iConsole.CursorWindowPosition() - aCursorPosition.iConsole.ViewPosition()) |
|
1700 { |
|
1701 } |
|
1702 |
|
1703 TViewPosition::TViewPosition(const TBufferPosition& aBufferPosition) |
|
1704 : iConsole(aBufferPosition.iConsole) |
|
1705 , iPoint(aBufferPosition.iPoint - aBufferPosition.iConsole.ViewPosition()) |
|
1706 { |
|
1707 } |
|
1708 |
|
1709 //______________________________________________________________________________ |
|
1710 // TScreenPosition |
|
1711 TScreenPosition::TScreenPosition(const CConsoleControl& aConsole, TPoint aPosition) |
|
1712 : iConsole(aConsole), iPoint(aPosition) |
|
1713 { |
|
1714 } |
|
1715 |
|
1716 TScreenPosition::TScreenPosition(const CConsoleControl& aConsole, TInt aX, TInt aY) |
|
1717 : iConsole(aConsole), iPoint(aX, aY) |
|
1718 { |
|
1719 } |
|
1720 |
|
1721 TScreenPosition::TScreenPosition(const TViewPosition& aViewPosition) |
|
1722 : iConsole(aViewPosition.iConsole) |
|
1723 , iPoint(aViewPosition.iPoint.iX * aViewPosition.iConsole.GlyphSize().iWidth, aViewPosition.iPoint.iY * aViewPosition.iConsole.GlyphSize().iHeight) |
|
1724 { |
|
1725 } |
|
1726 |
|
1727 //______________________________________________________________________________ |
|
1728 // RAttributeMap |
|
1729 |
|
1730 RAttributeMap::RAttributeMap() |
|
1731 : iAttributes(KAttributeMapGranularity, _FOFF(TAttributes, iPosition)) |
|
1732 { |
|
1733 } |
|
1734 |
|
1735 void RAttributeMap::Close() |
|
1736 { |
|
1737 iAttributes.Close(); |
|
1738 } |
|
1739 |
|
1740 void RAttributeMap::Reset() |
|
1741 { |
|
1742 iAttributes.Reset(); |
|
1743 } |
|
1744 |
|
1745 void RAttributeMap::AddL(TInt aPosition, TInt aLineWidth, const ConsoleAttributes::TAttributes& aAttributes) |
|
1746 { |
|
1747 // Take a copy of the attributes array to make cleanup easier. |
|
1748 RArray<TAttributes> attributes; |
|
1749 CleanupClosePushL(attributes); |
|
1750 const TInt numAttributes = iAttributes.Count(); |
|
1751 for (TInt i = 0; i < numAttributes; ++i) |
|
1752 { |
|
1753 attributes.AppendL(iAttributes[i]); |
|
1754 } |
|
1755 |
|
1756 if (attributes.Count() == 0) |
|
1757 { |
|
1758 // This is the first set of attributes to be added. Add a default set before them. |
|
1759 attributes.AppendL(TAttributes(0, DefaultAttributes())); |
|
1760 } |
|
1761 |
|
1762 TAttributes attr(aPosition, aAttributes); |
|
1763 TInt pos; |
|
1764 TInt err = attributes.FindInSignedKeyOrder(attr, pos); |
|
1765 if (err == KErrNone) |
|
1766 { |
|
1767 // Attribute already exists at this position - replace. |
|
1768 attributes[pos] = attr; |
|
1769 } |
|
1770 else |
|
1771 { |
|
1772 // No attribute found at aPosition. |
|
1773 // pos is set to the index _after_ aPosition. This must be at least 1 because the first slot in the array is always taken with defaults or something else. |
|
1774 // Set pos to the index _before_ aPosition. |
|
1775 --pos; |
|
1776 |
|
1777 // Check earlier attributes to see if they match. |
|
1778 if (!(attributes[pos] == attr)) |
|
1779 { |
|
1780 // No match - insert new attributes. |
|
1781 attributes.InsertInSignedKeyOrderL(attr); |
|
1782 |
|
1783 // Get the position of the newly inserted attributes. |
|
1784 attributes.FindInSignedKeyOrder(attr, pos); |
|
1785 } |
|
1786 } |
|
1787 |
|
1788 const TAttributes& newAttributes = attributes[pos]; |
|
1789 if ((pos == (attributes.Count() - 1)) && (newAttributes.iPosition < (aLineWidth - 1)) && !(newAttributes == TAttributes(0, DefaultAttributes()))) |
|
1790 { |
|
1791 // New attributes are the last in the list, and not at the end of the line and not defaults. |
|
1792 // Add another set of defaults after them. |
|
1793 attributes.AppendL(TAttributes(newAttributes.iPosition + 1, DefaultAttributes())); |
|
1794 } |
|
1795 |
|
1796 iAttributes.Close(); |
|
1797 iAttributes = attributes; |
|
1798 CleanupStack::Pop(&attributes); |
|
1799 } |
|
1800 |
|
1801 void RAttributeMap::RemoveFrom(TInt aPosition) |
|
1802 { |
|
1803 for (TInt i = (iAttributes.Count() - 1); i >= 0; --i) |
|
1804 { |
|
1805 if (iAttributes[i].iPosition >= aPosition) |
|
1806 { |
|
1807 iAttributes.Remove(i); |
|
1808 } |
|
1809 } |
|
1810 } |
|
1811 |
|
1812 TInt RAttributeMap::NumberOfBlocks() const |
|
1813 { |
|
1814 if (iAttributes.Count() == 0) |
|
1815 { |
|
1816 return 1; // If no attributes have been added, give the entire line an implict default set of attributes. |
|
1817 } |
|
1818 return iAttributes.Count(); |
|
1819 } |
|
1820 |
|
1821 void RAttributeMap::GetBlock(TInt aIndex, TInt aLineWidth, TInt& aStartPosition, TInt& aEndPosition, ConsoleAttributes::TAttributes& aAttributes) const |
|
1822 { |
|
1823 if (iAttributes.Count() == 0) |
|
1824 { |
|
1825 ASSERT(aIndex == 0); |
|
1826 aStartPosition = 0; |
|
1827 aEndPosition = aLineWidth; |
|
1828 aAttributes = DefaultAttributes(); |
|
1829 } |
|
1830 else |
|
1831 { |
|
1832 const TAttributes& attributes = iAttributes[aIndex]; |
|
1833 aAttributes = attributes.iAttributes; |
|
1834 aStartPosition = attributes.iPosition; |
|
1835 |
|
1836 if ((iAttributes.Count() == 1) || (aIndex == (iAttributes.Count() - 1))) |
|
1837 { |
|
1838 aEndPosition = aLineWidth; |
|
1839 } |
|
1840 else |
|
1841 { |
|
1842 aEndPosition = iAttributes[aIndex + 1].iPosition; |
|
1843 } |
|
1844 } |
|
1845 } |
|
1846 |
|
1847 RAttributeMap::TAttributes::TAttributes(TInt aPosition, const ConsoleAttributes::TAttributes& aAttributes) |
|
1848 : iPosition(aPosition), iAttributes(aAttributes) |
|
1849 { |
|
1850 } |
|
1851 |
|
1852 TBool RAttributeMap::TAttributes::operator==(const TAttributes& aAttributes) const |
|
1853 { |
|
1854 // Note, intentionally ignoring iPosition so ensure that existing attribute block are extended where possible. |
|
1855 return ((iAttributes.iAttributes == aAttributes.iAttributes.iAttributes) && |
|
1856 (iAttributes.iForegroundColor == aAttributes.iAttributes.iForegroundColor) && |
|
1857 (iAttributes.iBackgroundColor == aAttributes.iAttributes.iBackgroundColor)); |
|
1858 } |