|
1 /* |
|
2 * Copyright (c) 1997-1999 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "EIKCONCL.H" |
|
20 #include "EIKCONCL.PAN" |
|
21 #include <eikconso.h> |
|
22 #include <eikenv.h> |
|
23 #include <eikappui.h> |
|
24 #include <basched.h> |
|
25 #include <apgwgnam.h> |
|
26 #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
27 #include <eikdef.h> |
|
28 #else |
|
29 #include <eikdef.h> |
|
30 #include <uikon/eikdefmacros.h> |
|
31 #endif |
|
32 #include <avkon.hrh> |
|
33 #include <aknSctDialog.h> |
|
34 #include <avkon.rsg> |
|
35 #include <c32comm.h> |
|
36 #include <aknappui.h> |
|
37 |
|
38 GLDEF_C void Panic(TEikConClPanic aPanic) |
|
39 { |
|
40 _LIT(KPanicCat,"EIKON-CONCL"); |
|
41 User::Panic(KPanicCat,aPanic); |
|
42 } |
|
43 |
|
44 class CEikConsMessager; |
|
45 |
|
46 class CCommsKeyReader : public CActive |
|
47 { |
|
48 public: |
|
49 CCommsKeyReader(RComm& aComm, CEikConsMessager* aMessager); |
|
50 ~CCommsKeyReader(); |
|
51 |
|
52 private: |
|
53 void RunL(); |
|
54 void DoCancel(); |
|
55 void Start(); |
|
56 |
|
57 private: |
|
58 RComm& iComm; |
|
59 CEikConsMessager* iMessager; |
|
60 TBuf8<1> iBuf; |
|
61 TBuf8<4> iMatch; |
|
62 }; |
|
63 |
|
64 |
|
65 class CCommsKeyWriter : public CActive |
|
66 { |
|
67 public: |
|
68 CCommsKeyWriter(RComm& aComm); |
|
69 ~CCommsKeyWriter(); |
|
70 |
|
71 void Write(const TDesC& aDes); |
|
72 |
|
73 private: |
|
74 void WriteIfReady(); |
|
75 void RunL(); |
|
76 void DoCancel(); |
|
77 void AppendBlocking(TText8 aChar); |
|
78 |
|
79 private: |
|
80 RComm& iComm; |
|
81 TBuf8<256> iBuf; |
|
82 TBuf8<256> iWrite; |
|
83 TBool iInFakeCancel; |
|
84 }; |
|
85 |
|
86 |
|
87 enum |
|
88 { |
|
89 EExit, |
|
90 ERead, |
|
91 EReadCancel, |
|
92 EWrite, |
|
93 ESetCursorPosAbs, |
|
94 ESetCursorPosRel, |
|
95 ESetCursorHeight, |
|
96 ESetTitle, |
|
97 EClearScreen, |
|
98 EClearToEndOfLine |
|
99 }; |
|
100 |
|
101 |
|
102 struct TFepKey |
|
103 { |
|
104 TText iLong; |
|
105 const TText* iLower; |
|
106 const TText* iUpper; |
|
107 }; |
|
108 |
|
109 const TFepKey KFepKeyTable[] = |
|
110 { |
|
111 { '0', _S(" 0\r"), _S(" 0\r") }, |
|
112 { '1', _S("\\.:1#*/-+=\"',()|`!$%^&_[]{};@~<>?"), _S("\\.:1#*/-+=\"',()|`!$%^&_[]{};@~<>?") }, |
|
113 { '2', _S("abc2"), _S("ABC2") }, |
|
114 { '3', _S("def3"), _S("DEF3") }, |
|
115 { '4', _S("ghi4"), _S("GHI4") }, |
|
116 { '5', _S("jkl5"), _S("JKL5") }, |
|
117 { '6', _S("mno6"), _S("MNO6") }, |
|
118 { '7', _S("pqrs7"), _S("PQRS7") }, |
|
119 { '8', _S("tuv8"), _S("TUV8") }, |
|
120 { '9', _S("wxyz9"), _S("WXYZ9") } |
|
121 }; |
|
122 |
|
123 const TText* const KModeNames[] = |
|
124 { |
|
125 _S("Lower"), |
|
126 _S("Caps"), |
|
127 _S("Numeric") |
|
128 }; |
|
129 |
|
130 const TText* const KIOModeNames[] = |
|
131 { |
|
132 _S("Screen"), |
|
133 _S("Serial"), |
|
134 _S("Ansi-Serial") |
|
135 }; |
|
136 |
|
137 _LIT(KCommModule, "IRCOMM"); |
|
138 _LIT(KCommPort, "IRCOMM::0"); |
|
139 |
|
140 // |
|
141 // class CEikConsMessager |
|
142 // |
|
143 |
|
144 class CEikConsMessager : public CActive |
|
145 { |
|
146 public: |
|
147 enum TMyFlags |
|
148 { |
|
149 EShift, |
|
150 EDigitPressed |
|
151 }; |
|
152 enum TKeyMode |
|
153 { |
|
154 ELower, |
|
155 ECaps, |
|
156 ENumeric, |
|
157 ENumModes |
|
158 }; |
|
159 enum TIOMode |
|
160 { |
|
161 EScreen, |
|
162 ESerial, |
|
163 EAnsi, |
|
164 ENumIOModes |
|
165 }; |
|
166 public: |
|
167 CEikConsMessager(CEikConsoleScreen* aScreen,RThread aParentThread); |
|
168 ~CEikConsMessager(); |
|
169 void ConstructL(CEikConsoleClient* aClient); |
|
170 void HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType); |
|
171 void AddKeyEvent(const TKeyEvent& aKeyEvent); |
|
172 private: // overridden |
|
173 void RunL(); |
|
174 void DoCancel(); |
|
175 private: // internal |
|
176 void CompleteReadRequest(); |
|
177 private: // fep like stuff |
|
178 void StartTimer(); |
|
179 static TInt TimerCallBack(TAny* aThis); |
|
180 void DoTimer(); |
|
181 void LaunchSCTL(); |
|
182 void HandleDigit(const TKeyEvent& aKeyEvent, TEventCode aType); |
|
183 void StartCommsL(); |
|
184 void StopComms(); |
|
185 void WriteComms(const TDesC& aMsg); |
|
186 |
|
187 private: |
|
188 CEikConsoleScreen* iScreen; |
|
189 RThread iParentThread; |
|
190 TRequestStatus* iReadStatus; |
|
191 TKeyEvent* iKeyEvent; |
|
192 TInt iMessage; |
|
193 const TAny* iParam; |
|
194 TRequestStatus* iReplyStatus; |
|
195 CCirBuf<TKeyEvent>* iKeyQ; |
|
196 |
|
197 // fep like stuff |
|
198 TKeyEvent iLastKey; |
|
199 CPeriodic* iTimer; |
|
200 TBitFlags iFlags; |
|
201 TInt iMultiStep; |
|
202 TKeyMode iKeyMode; |
|
203 TIOMode iIOMode; |
|
204 RCommServ iCommServ; |
|
205 RComm iComm; |
|
206 CCommsKeyReader* iReader; |
|
207 CCommsKeyWriter* iWriter; |
|
208 }; |
|
209 |
|
210 CEikConsMessager::CEikConsMessager(CEikConsoleScreen* aScreen,RThread aParentThread) |
|
211 : CActive(EActivePriorityIpcEventsHigh), |
|
212 iParentThread(aParentThread) |
|
213 { |
|
214 iScreen=aScreen; |
|
215 } |
|
216 |
|
217 CEikConsMessager::~CEikConsMessager() |
|
218 { |
|
219 StopComms(); |
|
220 delete iTimer; |
|
221 iParentThread.Close(); |
|
222 delete iKeyQ; |
|
223 } |
|
224 |
|
225 void CEikConsMessager::ConstructL(CEikConsoleClient* aClient) |
|
226 { |
|
227 iTimer = CPeriodic::NewL(EPriorityStandard); |
|
228 iKeyQ=new(ELeave) CCirBuf<TKeyEvent>; |
|
229 iKeyQ->SetLengthL(40); // buffer length, too high? too low? |
|
230 iKeyEvent=(&aClient->iKeyEvent); |
|
231 aClient->iThreadStatus=(&iStatus); |
|
232 aClient->iMessage=(&iMessage); |
|
233 aClient->iParam=(&iParam); |
|
234 aClient->iReplyStatus=(&iReplyStatus); |
|
235 aClient->iScreen=iScreen; |
|
236 CActiveScheduler::Add(this); |
|
237 iStatus=KRequestPending; |
|
238 SetActive(); |
|
239 } |
|
240 |
|
241 void CEikConsMessager::DoCancel() |
|
242 { |
|
243 } |
|
244 |
|
245 void CEikConsMessager::RunL() |
|
246 { |
|
247 switch (iMessage) |
|
248 { |
|
249 case EExit: |
|
250 CBaActiveScheduler::Exit(); |
|
251 break; |
|
252 case ERead: |
|
253 if (iReadStatus) |
|
254 Panic(EEikConClPanicReadAlreadyOutstanding); |
|
255 iReadStatus=(TRequestStatus*)iParam; |
|
256 if (iKeyQ->Count()>0) // already a buffered event |
|
257 CompleteReadRequest(); |
|
258 break; |
|
259 case EReadCancel: |
|
260 if (iReadStatus) |
|
261 iParentThread.RequestComplete(iReadStatus,KErrCancel); |
|
262 break; |
|
263 case EWrite: |
|
264 iScreen->Write(*(const TDesC*)iParam); |
|
265 if (iIOMode != EScreen) |
|
266 WriteComms(*(const TDesC*)iParam); |
|
267 break; |
|
268 case ESetCursorPosAbs: |
|
269 iScreen->SetCursorPosAbs(*(const TPoint*)iParam); |
|
270 if (iIOMode == EAnsi) |
|
271 { |
|
272 TPoint point = iScreen->CursorPos(); |
|
273 TBuf<10> buf; |
|
274 buf.Format(_L("\033[%d;%dH"), point.iY, point.iX); |
|
275 WriteComms(buf); |
|
276 } |
|
277 break; |
|
278 case ESetCursorPosRel: |
|
279 iScreen->SetCursorPosRel(*(const TPoint*)iParam); |
|
280 if (iIOMode == EAnsi) |
|
281 { |
|
282 TPoint point = iScreen->CursorPos(); |
|
283 TBuf<10> buf; |
|
284 buf.Format(_L("\033[%d;%dH"), point.iY, point.iX); |
|
285 WriteComms(buf); |
|
286 } |
|
287 break; |
|
288 case ESetCursorHeight: |
|
289 iScreen->SetCursorHeight((TInt)iParam); |
|
290 break; |
|
291 case EClearScreen: |
|
292 iScreen->ClearScreen(); |
|
293 if (iIOMode == EAnsi) |
|
294 { |
|
295 WriteComms(_L("\033[2J")); |
|
296 } |
|
297 break; |
|
298 case EClearToEndOfLine: |
|
299 iScreen->ClearToEndOfLine(); |
|
300 if (iIOMode == EAnsi) |
|
301 { |
|
302 WriteComms(_L("\033[K")); |
|
303 } |
|
304 break; |
|
305 } |
|
306 iStatus=KRequestPending; |
|
307 SetActive(); |
|
308 iParentThread.RequestComplete(iReplyStatus,0); |
|
309 } |
|
310 |
|
311 void CEikConsMessager::CompleteReadRequest() |
|
312 { |
|
313 if (iReadStatus) |
|
314 { |
|
315 iKeyQ->Remove(iKeyEvent);; |
|
316 iParentThread.RequestComplete(iReadStatus,0); |
|
317 } |
|
318 } |
|
319 |
|
320 void CEikConsMessager::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType) |
|
321 { |
|
322 iFlags.Assign(EShift, aKeyEvent.iModifiers & EModifierShift); |
|
323 |
|
324 if ('0' <= aKeyEvent.iScanCode && aKeyEvent.iScanCode <= '9') |
|
325 { |
|
326 HandleDigit(aKeyEvent, aType); |
|
327 } |
|
328 else if (aKeyEvent.iScanCode == EStdKeyHash) |
|
329 { |
|
330 if (aType == EEventKeyDown) |
|
331 { |
|
332 if (iFlags[EShift]) |
|
333 { |
|
334 iIOMode = TIOMode((iIOMode+1)%ENumIOModes); |
|
335 User::InfoPrint(TPtrC(KIOModeNames[iIOMode])); |
|
336 if (iIOMode == ESerial) |
|
337 { |
|
338 StartCommsL(); |
|
339 } |
|
340 else if (iIOMode == EScreen) |
|
341 StopComms(); |
|
342 } |
|
343 else |
|
344 { |
|
345 iKeyMode = TKeyMode((iKeyMode+1)%ENumModes); |
|
346 User::InfoPrint(TPtrC(KModeNames[iKeyMode])); |
|
347 } |
|
348 iTimer->Cancel(); |
|
349 } |
|
350 } |
|
351 else if (aType == EEventKey) |
|
352 { |
|
353 if (aKeyEvent.iCode == '*') |
|
354 { |
|
355 LaunchSCTL(); |
|
356 iTimer->Cancel(); |
|
357 } |
|
358 else if (aKeyEvent.iCode != EKeyF21) |
|
359 { |
|
360 AddKeyEvent(aKeyEvent); |
|
361 iTimer->Cancel(); |
|
362 } |
|
363 } |
|
364 } |
|
365 |
|
366 void CEikConsMessager::AddKeyEvent(const TKeyEvent& aKeyEvent) |
|
367 { |
|
368 TInt ret=iKeyQ->Add(&aKeyEvent); |
|
369 if (ret==0) |
|
370 CEikonEnv::Beep(); |
|
371 if (iKeyQ->Count()==1) // client may be waiting on this key event |
|
372 CompleteReadRequest(); |
|
373 } |
|
374 |
|
375 void CEikConsMessager::LaunchSCTL() |
|
376 { |
|
377 TBuf<8> specialChars; |
|
378 TBool shift = !COMPARE_BOOLS(iFlags[EShift], (iKeyMode==ECaps)); |
|
379 TInt sctCase = (shift ? EAknSCTUpperCase : EAknSCTLowerCase); |
|
380 CAknCharMapDialog* dialog=new(ELeave) CAknCharMapDialog(sctCase, specialChars); |
|
381 if (dialog->ExecuteLD(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG)) |
|
382 { |
|
383 TKeyEvent event = { 0, 0, 0, 0 }; |
|
384 for ( TInt ii = 0; ii < specialChars.Length(); ii++) |
|
385 { |
|
386 if ( specialChars[ii] == 0x000A ) // 0x000A is line feed |
|
387 { |
|
388 event.iCode = EKeyEnter; |
|
389 event.iScanCode = EKeyEnter; |
|
390 } |
|
391 else |
|
392 { |
|
393 event.iCode = specialChars[ii]; |
|
394 event.iScanCode = specialChars[ii]; |
|
395 } |
|
396 AddKeyEvent(event); |
|
397 } |
|
398 } |
|
399 } |
|
400 |
|
401 void CEikConsMessager::HandleDigit(const TKeyEvent& aKeyEvent, TEventCode aType) |
|
402 { |
|
403 TText digit = TText(aKeyEvent.iScanCode); |
|
404 __ASSERT_DEBUG('0' <= digit && digit <= '9', Panic(EEikConClPanicIllegalFepChar)); |
|
405 TBool shift = !COMPARE_BOOLS(iFlags[EShift], (iKeyMode==ECaps)); |
|
406 const TFepKey& fepKey = KFepKeyTable[digit - '0']; |
|
407 TPtrC keys(shift ? fepKey.iUpper : fepKey.iLower); |
|
408 |
|
409 if (iKeyMode == ENumeric) |
|
410 { |
|
411 if (aType == EEventKey) |
|
412 { |
|
413 AddKeyEvent(aKeyEvent); |
|
414 iTimer->Cancel(); |
|
415 } |
|
416 } |
|
417 else |
|
418 { |
|
419 if (aType == EEventKeyDown) |
|
420 { |
|
421 iFlags.Set(EDigitPressed); |
|
422 if (digit == iLastKey.iScanCode) |
|
423 { |
|
424 iMultiStep = (iMultiStep + 1) % keys.Length(); |
|
425 TKeyEvent del = {EKeyBackspace, EStdKeyBackspace, 0, 0}; |
|
426 AddKeyEvent(del); |
|
427 TKeyEvent event = {keys[iMultiStep], keys[iMultiStep], 0, 0}; |
|
428 AddKeyEvent(event); |
|
429 } |
|
430 else |
|
431 { |
|
432 iMultiStep = 0; |
|
433 TKeyEvent event = {keys[iMultiStep], keys[iMultiStep], 0, 0}; |
|
434 AddKeyEvent(event); |
|
435 } |
|
436 |
|
437 StartTimer(); |
|
438 iLastKey = aKeyEvent; |
|
439 } |
|
440 else if (aType == EEventKeyUp) |
|
441 { |
|
442 iFlags.Clear(EDigitPressed); |
|
443 } |
|
444 } |
|
445 } |
|
446 |
|
447 void CEikConsMessager::StartTimer() |
|
448 { |
|
449 iTimer->Cancel(); |
|
450 iTimer->Start(800000, 1000000, TCallBack(TimerCallBack, this)); |
|
451 } |
|
452 |
|
453 TInt CEikConsMessager::TimerCallBack(TAny* aThis) |
|
454 { |
|
455 ((CEikConsMessager*)aThis)->DoTimer(); |
|
456 return 0; |
|
457 } |
|
458 |
|
459 void CEikConsMessager::DoTimer() |
|
460 { |
|
461 if (iFlags[EDigitPressed]) |
|
462 { |
|
463 TText digit = TText(iLastKey.iScanCode); |
|
464 __ASSERT_DEBUG('0' <= digit && digit <= '9', Panic(EEikConClPanicIllegalFepChar)); |
|
465 TText key = KFepKeyTable[digit - '0'].iLong; |
|
466 TKeyEvent del = {EKeyBackspace, EStdKeyBackspace, 0, 0}; |
|
467 AddKeyEvent(del); |
|
468 TKeyEvent event = {key, key, 0, 0}; |
|
469 AddKeyEvent(event); |
|
470 iFlags.Clear(EDigitPressed); |
|
471 } |
|
472 |
|
473 iLastKey.iScanCode = 0; |
|
474 iMultiStep = 0; |
|
475 } |
|
476 |
|
477 void CEikConsMessager::StartCommsL() |
|
478 { |
|
479 User::LeaveIfError(iCommServ.Connect()); |
|
480 User::LeaveIfError(iCommServ.LoadCommModule(KCommModule)); |
|
481 User::LeaveIfError(iComm.Open(iCommServ, KCommPort, ECommExclusive)); |
|
482 TCommConfig cBuf; |
|
483 iComm.Config(cBuf); |
|
484 TCommConfigV01& c=cBuf(); |
|
485 c.iRate=EBps115200; |
|
486 c.iDataBits=EData8; |
|
487 c.iStopBits=EStop1; |
|
488 c.iParity=EParityNone; |
|
489 User::LeaveIfError(iComm.SetConfig(cBuf)); |
|
490 delete iReader; |
|
491 iReader=0; |
|
492 iReader = new(ELeave) CCommsKeyReader(iComm, this); |
|
493 delete iWriter; |
|
494 iWriter=0; |
|
495 iWriter = new(ELeave) CCommsKeyWriter(iComm); |
|
496 } |
|
497 |
|
498 void CEikConsMessager::StopComms() |
|
499 { |
|
500 delete iWriter; |
|
501 iWriter=0; |
|
502 delete iReader; |
|
503 iReader=0; |
|
504 iComm.Close(); |
|
505 iCommServ.Close(); |
|
506 } |
|
507 |
|
508 void CEikConsMessager::WriteComms(const TDesC& aMsg) |
|
509 { |
|
510 if (iWriter) |
|
511 { |
|
512 iWriter->Write(aMsg); |
|
513 } |
|
514 } |
|
515 |
|
516 |
|
517 struct TEscSeq |
|
518 { |
|
519 TText8 iText[4]; |
|
520 TKeyCode iCode; |
|
521 TStdScanCode iScanCode; |
|
522 }; |
|
523 |
|
524 const TEscSeq KEscSeqs[] = |
|
525 { |
|
526 {"[?D", EKeyLeftArrow, EStdKeyLeftArrow}, |
|
527 {"[?C", EKeyRightArrow, EStdKeyRightArrow}, |
|
528 {"[?A", EKeyUpArrow, EStdKeyUpArrow}, |
|
529 {"[?B", EKeyDownArrow, EStdKeyDownArrow} |
|
530 }; |
|
531 |
|
532 |
|
533 CCommsKeyReader::CCommsKeyReader(RComm& aComm, CEikConsMessager* aMessager) |
|
534 : CActive(EPriorityHigh), iComm(aComm), iMessager(aMessager) |
|
535 { |
|
536 CActiveScheduler::Add(this); |
|
537 Start(); |
|
538 } |
|
539 |
|
540 CCommsKeyReader::~CCommsKeyReader() |
|
541 { |
|
542 Cancel(); |
|
543 } |
|
544 |
|
545 void CCommsKeyReader::RunL() |
|
546 { |
|
547 if (iStatus == KErrNone) |
|
548 { |
|
549 Start(); |
|
550 if (iMatch.Length() || iBuf[0]=='[') |
|
551 { |
|
552 iMatch.Append(iBuf[0]); |
|
553 for (TInt i=0; i<4; i++) |
|
554 { |
|
555 if (iMatch.Match(TPtrC8(KEscSeqs[i].iText)) == 0) |
|
556 { |
|
557 TKeyEvent event = {KEscSeqs[i].iCode, KEscSeqs[i].iScanCode, 0, 0}; |
|
558 iMessager->AddKeyEvent(event); |
|
559 iMatch.Zero(); |
|
560 return; |
|
561 } |
|
562 } |
|
563 if (iMatch.Length() >= 3) |
|
564 iMatch.Zero(); |
|
565 else |
|
566 return; |
|
567 } |
|
568 TKeyEvent event = {iBuf[0], iBuf[0], 0, 0}; |
|
569 iMessager->AddKeyEvent(event); |
|
570 } |
|
571 } |
|
572 |
|
573 void CCommsKeyReader::DoCancel() |
|
574 { |
|
575 iComm.ReadCancel(); |
|
576 } |
|
577 |
|
578 void CCommsKeyReader::Start() |
|
579 { |
|
580 iComm.ReadOneOrMore(iStatus, iBuf); |
|
581 SetActive(); |
|
582 } |
|
583 |
|
584 |
|
585 CCommsKeyWriter::CCommsKeyWriter(RComm& aComm) |
|
586 : CActive(EPriorityStandard), iComm(aComm), iInFakeCancel(EFalse) |
|
587 { |
|
588 CActiveScheduler::Add(this); |
|
589 } |
|
590 |
|
591 CCommsKeyWriter::~CCommsKeyWriter() |
|
592 { |
|
593 Cancel(); |
|
594 } |
|
595 |
|
596 void CCommsKeyWriter::Write(const TDesC& aDes) |
|
597 { |
|
598 for (TInt i=0; i<aDes.Length(); i++) |
|
599 { |
|
600 if (aDes[i] == '\n') |
|
601 { |
|
602 AppendBlocking('\r'); |
|
603 } |
|
604 AppendBlocking(TText8(aDes[i])); |
|
605 } |
|
606 WriteIfReady(); |
|
607 } |
|
608 |
|
609 void CCommsKeyWriter::WriteIfReady() |
|
610 { |
|
611 if (!IsActive() && iBuf.Length()>0) |
|
612 { |
|
613 iWrite=iBuf; |
|
614 iBuf.Zero(); |
|
615 iComm.Write(iStatus, iWrite); |
|
616 SetActive(); |
|
617 } |
|
618 } |
|
619 |
|
620 void CCommsKeyWriter::AppendBlocking(TText8 aChar) |
|
621 { |
|
622 if (iBuf.Length() >= iBuf.MaxLength()) |
|
623 { |
|
624 RTimer t; |
|
625 t.CreateLocal(); |
|
626 TRequestStatus tR; |
|
627 t.After(tR, 2000000); // 2 second timeout |
|
628 User::WaitForRequest(iStatus, tR); |
|
629 if (iStatus != KRequestPending) |
|
630 { |
|
631 // write completed |
|
632 t.Cancel(); |
|
633 User::WaitForRequest(tR); |
|
634 |
|
635 if (IsActive()) |
|
636 { |
|
637 iInFakeCancel = ETrue; |
|
638 Cancel(); |
|
639 } |
|
640 |
|
641 iWrite.Zero(); |
|
642 WriteIfReady(); |
|
643 |
|
644 } |
|
645 else |
|
646 { |
|
647 // timeout, throw away the buffered data - sorry! |
|
648 iBuf.Zero(); |
|
649 } |
|
650 t.Close(); |
|
651 } |
|
652 |
|
653 iBuf.Append(aChar); |
|
654 } |
|
655 |
|
656 void CCommsKeyWriter::RunL() |
|
657 { |
|
658 iWrite.Zero(); |
|
659 WriteIfReady(); |
|
660 } |
|
661 |
|
662 void CCommsKeyWriter::DoCancel() |
|
663 { |
|
664 if (iInFakeCancel == EFalse) |
|
665 iComm.WriteCancel(); |
|
666 |
|
667 iInFakeCancel = EFalse; |
|
668 } |
|
669 |
|
670 |
|
671 |
|
672 // |
|
673 // class CEikConsAppUi |
|
674 // |
|
675 |
|
676 struct SCommandLine |
|
677 { |
|
678 RThread iParentThread; |
|
679 TRequestStatus* iStatus; |
|
680 CEikConsoleClient* iClient; |
|
681 TSize iSize; |
|
682 const TDesC* iTitle; |
|
683 }; |
|
684 |
|
685 class CEikConsAppUi : public CAknAppUi //CEikAppUi |
|
686 { |
|
687 public: |
|
688 DECLARE_TYPE_ID(0x2001b26a) |
|
689 public: |
|
690 void ConstructL(const SCommandLine* aComLine); |
|
691 ~CEikConsAppUi(); |
|
692 private: // overridden |
|
693 TKeyResponse HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType); |
|
694 void HandleForegroundEventL(TBool aForeground); |
|
695 void SetAndDrawFocus(TBool aFocus); |
|
696 protected: // from MObjectProvider |
|
697 virtual TTypeUid::Ptr MopSupplyObject(TTypeUid aId); |
|
698 virtual MObjectProvider* MopNext(); |
|
699 private: |
|
700 CEikConsoleScreen* iScreen; |
|
701 CEikConsoleControl* iControl; |
|
702 CEikConsMessager* iMessager; |
|
703 }; |
|
704 |
|
705 CEikConsAppUi::~CEikConsAppUi() |
|
706 { |
|
707 delete(iScreen); |
|
708 delete(iMessager); |
|
709 } |
|
710 |
|
711 void CEikConsAppUi::ConstructL(const SCommandLine* aComLine) |
|
712 { |
|
713 // CEikAppUi::BaseConstructL(ENoAppResourceFile); |
|
714 CAknAppUi::BaseConstructL(ENoAppResourceFile | ENoScreenFurniture | EAknEnableMSK); |
|
715 iScreen=new(ELeave) CEikConsoleScreen; |
|
716 iScreen->ConstructL(*(aComLine->iTitle),0); |
|
717 iControl=iScreen->ConsoleControl(); |
|
718 iControl->SetFocus(ETrue,EDrawNow); |
|
719 iMessager=new(ELeave) CEikConsMessager(iScreen,aComLine->iParentThread); |
|
720 iMessager->ConstructL(aComLine->iClient); |
|
721 RThread().SetPriority(EPriorityMore); |
|
722 } |
|
723 |
|
724 void CEikConsAppUi::HandleForegroundEventL(TBool aForeground) |
|
725 { |
|
726 if (aForeground) |
|
727 RThread().SetPriority(EPriorityMore); |
|
728 CEikAppUi::HandleForegroundEventL(aForeground); |
|
729 } |
|
730 |
|
731 void CEikConsAppUi::SetAndDrawFocus(TBool aFocus) |
|
732 { |
|
733 if (iControl) |
|
734 iControl->SetFocus(aFocus,EDrawNow); |
|
735 } |
|
736 |
|
737 TKeyResponse CEikConsAppUi::HandleKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType) |
|
738 { |
|
739 iMessager->HandleKeyEventL(aKeyEvent, aType); |
|
740 return EKeyWasConsumed; |
|
741 } |
|
742 |
|
743 TTypeUid::Ptr CEikConsAppUi::MopSupplyObject(TTypeUid aId) |
|
744 /** Retrieves an object of the same type as that encapsulated in aId. |
|
745 |
|
746 This function is used to allow to ask owners for access to |
|
747 other objects that they own. |
|
748 |
|
749 Other than in the case where NULL is returned, the object returned must be |
|
750 of the same object type - that is, the ETypeId member of the object pointed |
|
751 to by the pointer returned by this function must be equal to the iUid member |
|
752 of aId. |
|
753 |
|
754 @param aId An encapsulated object type ID. |
|
755 @return Encapsulates the pointer to the object provided. Note that the encapsulated |
|
756 pointer may be NULL. */ |
|
757 { |
|
758 if (aId.iUid == ETypeId) |
|
759 { |
|
760 // Touch compatibility mode uses this to detect console application |
|
761 return aId.MakePtr(this); |
|
762 } |
|
763 return TTypeUid::Null(); |
|
764 } |
|
765 |
|
766 MObjectProvider* CEikConsAppUi::MopNext() |
|
767 /** Retrieves the parent. |
|
768 |
|
769 @return A pointer to an object provider, or NULL if none is defined. |
|
770 @publishedAll |
|
771 @released */ |
|
772 { |
|
773 CEikonEnv* env=(CEikonEnv*)iCoeEnv; |
|
774 return env->AppUiFactory(); |
|
775 } |
|
776 |
|
777 // |
|
778 // class CConsEikonEnv |
|
779 // |
|
780 |
|
781 class CConsEikonEnv : public CEikonEnv |
|
782 { |
|
783 public: |
|
784 void ConstructConsoleEnvironmentL(const SCommandLine* aComLine); |
|
785 |
|
786 #if defined(SYMBIAN_UI_FRAMEWORKS_CONTROL_API_V2) |
|
787 private: |
|
788 IMPORT_C virtual void CEikonEnv_Reserved_1(); |
|
789 IMPORT_C virtual void CEikonEnv_Reserved_2(); |
|
790 IMPORT_C virtual void CEikonEnv_Reserved_3(); |
|
791 IMPORT_C virtual void CEikonEnv_Reserved_4(); |
|
792 IMPORT_C virtual void CEikonEnv_Reserved_5(); |
|
793 IMPORT_C virtual void CEikonEnv_Reserved_6(); |
|
794 IMPORT_C virtual void CEikonEnv_Reserved_7(); |
|
795 IMPORT_C virtual void CEikonEnv_Reserved_8(); |
|
796 IMPORT_C virtual void CEikonEnv_Reserved_9(); |
|
797 IMPORT_C virtual void CEikonEnv_Reserved_10(); |
|
798 #endif |
|
799 }; |
|
800 |
|
801 void CConsEikonEnv::ConstructConsoleEnvironmentL(const SCommandLine* aComLine) |
|
802 { |
|
803 ConstructL(); |
|
804 CEikConsAppUi* appUi=new(ELeave) CEikConsAppUi; |
|
805 appUi->ConstructL(aComLine); |
|
806 CApaWindowGroupName* wgName=CApaWindowGroupName::NewLC(iWsSession); |
|
807 TPtrC caption=*(aComLine->iTitle); |
|
808 wgName->SetCaptionL(caption); |
|
809 wgName->SetRespondsToShutdownEvent(EFalse); |
|
810 wgName->SetRespondsToSwitchFilesEvent(EFalse); |
|
811 wgName->SetWindowGroupName(iRootWin); |
|
812 CleanupStack::PopAndDestroy(); // wgName |
|
813 |
|
814 User::RenameProcess(caption); |
|
815 User::RenameThread(caption); |
|
816 } |
|
817 |
|
818 #if defined(SYMBIAN_UI_FRAMEWORKS_CONTROL_API_V2) |
|
819 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_1() |
|
820 { |
|
821 } |
|
822 |
|
823 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_2() |
|
824 { |
|
825 } |
|
826 |
|
827 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_3() |
|
828 { |
|
829 } |
|
830 |
|
831 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_4() |
|
832 { |
|
833 } |
|
834 |
|
835 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_5() |
|
836 { |
|
837 } |
|
838 |
|
839 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_6() |
|
840 { |
|
841 } |
|
842 |
|
843 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_7() |
|
844 { |
|
845 } |
|
846 |
|
847 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_8() |
|
848 { |
|
849 } |
|
850 |
|
851 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_9() |
|
852 { |
|
853 } |
|
854 |
|
855 EXPORT_C void CConsEikonEnv::CEikonEnv_Reserved_10() |
|
856 { |
|
857 } |
|
858 #endif |
|
859 |
|
860 TInt ConsoleClientStartFunction(TAny* aParam) |
|
861 { |
|
862 const SCommandLine* comLine=(const SCommandLine*)aParam; |
|
863 TInt err=KErrNoMemory; |
|
864 CConsEikonEnv* coe=new CConsEikonEnv; |
|
865 if (coe) |
|
866 { |
|
867 TRAP(err,coe->ConstructConsoleEnvironmentL(comLine)); |
|
868 } |
|
869 TRequestStatus* pS=(comLine->iStatus); |
|
870 comLine->iParentThread.RequestComplete(pS,err); |
|
871 if (!err) |
|
872 coe->ExecuteD(); |
|
873 return(0); |
|
874 } |
|
875 |
|
876 // |
|
877 // class CEikConsoleClient |
|
878 // |
|
879 |
|
880 CEikConsoleClient::~CEikConsoleClient() |
|
881 { |
|
882 if (iLogonStatus.Int()==KRequestPending && iReplyStatus) |
|
883 SendReceive(EExit,NULL); |
|
884 iThread.Close(); |
|
885 } |
|
886 |
|
887 CEikConsoleClient::CEikConsoleClient() |
|
888 { |
|
889 } |
|
890 |
|
891 const TInt KMaxHeapSize=0x1000*254; // chunks are a megabyte anyway |
|
892 |
|
893 TInt CEikConsoleClient::Create(const TDesC& aTitle,TSize aSize) |
|
894 { |
|
895 TInt err; |
|
896 TRequestStatus status=KRequestPending; |
|
897 SCommandLine comLine; |
|
898 comLine.iStatus=(&status); |
|
899 comLine.iClient=this; |
|
900 comLine.iSize=aSize; |
|
901 comLine.iTitle=&aTitle; |
|
902 TBuf<20> threadName; |
|
903 TInt num=0; |
|
904 do |
|
905 { |
|
906 _LIT(KTemp,"UI%02d"); |
|
907 threadName.Format(KTemp,num++); // !! review the title |
|
908 err=iThread.Create(threadName,ConsoleClientStartFunction,KDefaultStackSize,KMinHeapSize,KMaxHeapSize,&comLine,EOwnerThread); |
|
909 } while(err==KErrAlreadyExists); |
|
910 if (!err) |
|
911 { |
|
912 iThread.Logon(iLogonStatus); |
|
913 comLine.iParentThread.Duplicate(iThread); |
|
914 iThread.Resume(); |
|
915 User::WaitForRequest(status,iLogonStatus); |
|
916 err=status.Int(); |
|
917 } |
|
918 return(err); |
|
919 } |
|
920 |
|
921 void CEikConsoleClient::SendReceive(TInt aMessage,const TAny* aParam) |
|
922 { |
|
923 if (iLogonStatus.Int()!=KRequestPending) |
|
924 User::Exit(KErrCancel); |
|
925 *iMessage=aMessage; |
|
926 *iParam=aParam; |
|
927 TRequestStatus replyStatus=KRequestPending; |
|
928 *iReplyStatus=(&replyStatus); |
|
929 TRequestStatus* pS=iThreadStatus; |
|
930 iThread.RequestComplete(pS,0); |
|
931 User::WaitForRequest(replyStatus,iLogonStatus); |
|
932 } |
|
933 |
|
934 void CEikConsoleClient::Read(TRequestStatus& aStatus) |
|
935 { |
|
936 aStatus=KRequestPending; |
|
937 SendReceive(ERead,&aStatus); |
|
938 } |
|
939 |
|
940 void CEikConsoleClient::ReadCancel() |
|
941 { |
|
942 SendReceive(EReadCancel,NULL); |
|
943 } |
|
944 |
|
945 void CEikConsoleClient::Write(const TDesC& aDes) |
|
946 { |
|
947 SendReceive(EWrite,&aDes); |
|
948 } |
|
949 |
|
950 TPoint CEikConsoleClient::CursorPos() const |
|
951 { |
|
952 return(iScreen->CursorPos()); |
|
953 } |
|
954 |
|
955 void CEikConsoleClient::SetCursorPosAbs(const TPoint& aPosition) |
|
956 { |
|
957 SendReceive(ESetCursorPosAbs,&aPosition); |
|
958 } |
|
959 |
|
960 void CEikConsoleClient::SetCursorPosRel(const TPoint &aVector) |
|
961 { |
|
962 SendReceive(ESetCursorPosRel,&aVector); |
|
963 } |
|
964 |
|
965 void CEikConsoleClient::SetCursorHeight(TInt aPercentage) |
|
966 { |
|
967 SendReceive(ESetCursorHeight,aPercentage); |
|
968 } |
|
969 |
|
970 void CEikConsoleClient::SetTitle(const TDesC& aTitle) |
|
971 { |
|
972 SendReceive(ESetTitle,&aTitle); |
|
973 } |
|
974 |
|
975 void CEikConsoleClient::ClearScreen() |
|
976 { |
|
977 SendReceive(EClearScreen,NULL); |
|
978 } |
|
979 |
|
980 void CEikConsoleClient::ClearToEndOfLine() |
|
981 { |
|
982 SendReceive(EClearToEndOfLine,NULL); |
|
983 } |
|
984 |
|
985 TSize CEikConsoleClient::ScreenSize() const |
|
986 { |
|
987 return(iScreen->ScreenSize() ); |
|
988 } |
|
989 |
|
990 TKeyCode CEikConsoleClient::KeyCode() const |
|
991 { |
|
992 return((TKeyCode)iKeyEvent.iCode); |
|
993 } |
|
994 |
|
995 TUint CEikConsoleClient::KeyModifiers() const |
|
996 { |
|
997 return(iKeyEvent.iModifiers); |
|
998 } |
|
999 |
|
1000 extern "C" { |
|
1001 EXPORT_C TAny* NewConsole() |
|
1002 { |
|
1003 return(new CEikConsoleClient); |
|
1004 } |
|
1005 } |