extras/calcsoft/src/CalcDoc.cpp
changeset 0 3ee3dfdd8d69
child 19 99b535de1dda
equal deleted inserted replaced
-1:000000000000 0:3ee3dfdd8d69
       
     1 /*
       
     2 * Copyright (c) 2002 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:  Document class, CCalcDocument
       
    15 *                Derived from CEikDocument
       
    16 *                The history of inputted data is held.
       
    17 *                The memory of four-arithmetical-operations operation 
       
    18 *                or a calculation result is held.
       
    19 *                The last result and memory are saved at a file and 
       
    20 *                it restores.
       
    21 *
       
    22 */
       
    23 
       
    24 
       
    25 
       
    26 // INCLUDE FILES  
       
    27 #include    "CalcDoc.h"
       
    28 #include    "CalcEditline.h"
       
    29 #include    "CalcAppUi.h"
       
    30 #include    "CalcApp.h"
       
    31 #include	"CalcEnv.h"
       
    32 #include    "CalcHistory.h"
       
    33 #include	"e32math.h"
       
    34 #include <e32cmn.h>
       
    35 #include <s32file.h>
       
    36 // CONSTANTS
       
    37 const TReal64 KCalcDefaultMemory(0.0);
       
    38 const TReal64 KCalcDefaultLastResult(0.0);
       
    39 const TReal64 KCalcDefaultZero(1E-12);
       
    40 
       
    41 _LIT( KCalculatorFilename,"Calcsoft.ini");
       
    42 _LIT(KDelimiter, ":");
       
    43 
       
    44 // ================= MEMBER FUNCTIONS =======================
       
    45 
       
    46 // Two-phased constructor.
       
    47 CCalcDocument* CCalcDocument::NewL
       
    48                 (CEikApplication& aApp) 
       
    49     {
       
    50     CCalcDocument* self = new (ELeave) CCalcDocument(aApp);
       
    51     CleanupStack::PushL(self);
       
    52     self->ConstructL();
       
    53     CleanupStack::Pop(self);
       
    54     return self;
       
    55     }
       
    56 
       
    57 // Destructor
       
    58 CCalcDocument::~CCalcDocument()
       
    59     {
       
    60     delete iHistory;
       
    61     }
       
    62 
       
    63 // ---------------------------------------------------------
       
    64 // CCalcDocument::CalculateAndAddHistoryL
       
    65 // This function is called when State is changed to State3 or State5. 
       
    66 // (other items were commented in a header).
       
    67 // ---------------------------------------------------------
       
    68 //
       
    69 TReal64 CCalcDocument::CalculateAndAddHistoryL
       
    70                    (TReal64 aOperand,
       
    71                     const TCalcEditLine& aLine)
       
    72     {
       
    73 	iProvisionalResult = CalculateL(aOperand, aLine.Operator()); 
       
    74 	iHistory->Add(aLine);       // Add a line to history.	
       
    75 	return iProvisionalResult;	
       
    76     }
       
    77 
       
    78 // ---------------------------------------------------------
       
    79 // CCalcDocument::CalculateAndNoHistoryL
       
    80 // This function is called when the calculations is not
       
    81 // written to the Outputsheet (sqrt and percent in some cases).
       
    82 // (other items were commented in a header).
       
    83 // ---------------------------------------------------------
       
    84 //
       
    85 TReal64 CCalcDocument::CalculateAndNoHistoryL
       
    86                    (TReal64 aOperand,
       
    87                     const TCalcEditLine& aLine)
       
    88 	{
       
    89 	TReal64 result = CalculateL(aOperand, aLine.Operator()); 
       
    90 	return result;
       
    91 	}
       
    92 
       
    93 // ---------------------------------------------------------
       
    94 // CCalcDocument::CalculateAndModifyHistoryL
       
    95 // This function is called when the output needs to be edited
       
    96 // before it is displayed in the Outputsheet. This function 
       
    97 // may call the CalculateL twice, because it may need to
       
    98 // calculate the percent first.
       
    99 // (other items were commented in a header).
       
   100 // ---------------------------------------------------------
       
   101 //
       
   102 TReal64 CCalcDocument::CalculateAndModifyHistoryL
       
   103                    (TReal64 aOperand,
       
   104                     TCalcEditLine& aLine,
       
   105 					TCalcEditLine::TCalcOperatorType aOperator)
       
   106 	{
       
   107 	if (aOperator == TCalcEditLine::ECalcMultiply)
       
   108 		iProvisionalResult = CalculateL(aOperand, aLine.Operator()); 
       
   109 	else
       
   110 		{
       
   111 		TReal64 iTempResult = CalculateL(aOperand, aLine.Operator()); 
       
   112 		iProvisionalResult = CalculateL(iTempResult, aOperator);
       
   113 		}
       
   114 
       
   115 	aLine.SetOperator(aOperator);
       
   116 	// Get the percent character from iCalcAppEnv (it uses the resource
       
   117 	// file to get the character).
       
   118 	TChar character((iCalcAppEnv->OutSheetOperator(TCalcEditLine::ECalcPercent))[0]);
       
   119 	aLine.AppendNumberStringL(character); // Add percent to the line
       
   120 	iHistory->Add(aLine);       // Add a line to history.	
       
   121 	return iProvisionalResult;
       
   122 	}
       
   123 
       
   124 // ---------------------------------------------------------
       
   125 // CCalcDocument::AddEqualLineAndUpdateLastResult
       
   126 // This is called when "Equal" command is selected. 
       
   127 // (other items were commented in a header).
       
   128 // ---------------------------------------------------------
       
   129 //
       
   130 void CCalcDocument::AddEqualLineAndUpdateLastResultL()
       
   131     {
       
   132     TCalcEditLine line;
       
   133     line.SetOperator(TCalcEditLine::ECalcEqual);
       
   134     line.SetNumber(iProvisionalResult);
       
   135     iHistory->Add(line);         // Add a line to history.
       
   136     iLastResult = iProvisionalResult;
       
   137     SaveStateL();
       
   138     }
       
   139 
       
   140 // ---------------------------------------------------------
       
   141 // CCalcDocument::AddEmptyLine
       
   142 // Add a empty line
       
   143 // (other items were commented in a header).
       
   144 // ---------------------------------------------------------
       
   145 //
       
   146 void CCalcDocument::AddEmptyLine()
       
   147     {
       
   148     TCalcEditLine line;
       
   149     iHistory->Add(line);       
       
   150     }
       
   151 
       
   152 // ---------------------------------------------------------
       
   153 // CCalcDocument::MemorySave
       
   154 // Save a memory from value of current editor.
       
   155 // (other items were commented in a header).
       
   156 // ---------------------------------------------------------
       
   157 //
       
   158 void CCalcDocument::MemorySaveL
       
   159                    (TReal64 aNewMemory)
       
   160     {
       
   161     iMemory = aNewMemory;
       
   162     SaveStateL();
       
   163     }
       
   164 
       
   165 
       
   166 // ---------------------------------------------------------
       
   167 // CCalcDocument::HasMemory
       
   168 // Check memory non-zero.
       
   169 // (other items were commented in a header).
       
   170 // ---------------------------------------------------------
       
   171 //
       
   172 TBool CCalcDocument::HasMemory() const
       
   173     {
       
   174     return (iMemory != 0.0);
       
   175     }
       
   176 
       
   177 // ---------------------------------------------------------
       
   178 // CCalcDocument::Memory
       
   179 // Return memory.
       
   180 // (other items were commented in a header).
       
   181 // ---------------------------------------------------------
       
   182 //
       
   183 TReal64 CCalcDocument::Memory() const
       
   184     {
       
   185     return (iMemory);
       
   186     }
       
   187 
       
   188 // ---------------------------------------------------------
       
   189 // CCalcDocument::MemoryClear
       
   190 // Clear memory.
       
   191 // (other items were commented in a header).
       
   192 // ---------------------------------------------------------
       
   193 //
       
   194 void CCalcDocument::MemoryClearL()
       
   195     {
       
   196     iMemory = 0.0;
       
   197     SaveStateL(); 	
       
   198     }
       
   199 
       
   200 // ----------------------------------------------------
       
   201 // CCalcDocument::LastResult
       
   202 // Return Last result.
       
   203 // (other items were commented in a header).
       
   204 // ----------------------------------------------------
       
   205 //
       
   206 TReal64 CCalcDocument::LastResult() const
       
   207     {
       
   208     return (iLastResult);
       
   209     }
       
   210 
       
   211 // ----------------------------------------------------
       
   212 // CCalcDocument::ProvisionalResult
       
   213 // Return provisional result
       
   214 // (other items were commented in a header).
       
   215 // ----------------------------------------------------
       
   216 //
       
   217 TReal64 CCalcDocument::ProvisionalResult() const
       
   218     {
       
   219     return iProvisionalResult;
       
   220     }
       
   221 
       
   222 
       
   223 // ----------------------------------------------------
       
   224 // CCalcDocument::History
       
   225 // Return CCalcHistory class.
       
   226 // (other items were commented in a header).
       
   227 // ----------------------------------------------------
       
   228 //
       
   229 CCalcHistory* CCalcDocument::History() const
       
   230     {
       
   231     return iHistory;
       
   232     }
       
   233 
       
   234 
       
   235 // C++ default constructor can NOT contain any code, that
       
   236 // might leave.
       
   237 //
       
   238 CCalcDocument::CCalcDocument
       
   239                (CEikApplication& aApp) 
       
   240               : CEikDocument(aApp)
       
   241     {
       
   242     }
       
   243 
       
   244 // Second phase constructor.
       
   245 void CCalcDocument::ConstructL()
       
   246     {
       
   247     iHistory = new (ELeave) CCalcHistory();
       
   248     }
       
   249 
       
   250 // ---------------------------------------------------------
       
   251 // CCalcDocument::CalculateL
       
   252 // Calculate result
       
   253 // Leave may occur, causes KErrOverflow or KErrDivideByZero.
       
   254 // (other items were commented in a header).
       
   255 // ---------------------------------------------------------
       
   256 //
       
   257 TReal64 CCalcDocument::CalculateL
       
   258         (TReal64 aOperand,
       
   259          TCalcEditLine::TCalcOperatorType aOperator) 
       
   260     {
       
   261     TReal64  result(iProvisionalResult);
       
   262 
       
   263     switch (aOperator)
       
   264         {
       
   265         case  TCalcEditLine::ECalcAdd:
       
   266             {
       
   267             result += aOperand;
       
   268             break;
       
   269             }
       
   270         case  TCalcEditLine::ECalcSubtract:
       
   271             {
       
   272             result -= aOperand;
       
   273             if( Abs(result)<= KCalcDefaultZero )
       
   274             	{
       
   275             	result = 0;
       
   276             	}
       
   277             break;
       
   278             }
       
   279         case  TCalcEditLine::ECalcMultiply:
       
   280             {
       
   281             result *= aOperand;
       
   282             break;
       
   283             }
       
   284         case  TCalcEditLine::ECalcDivide:
       
   285             {
       
   286             if ( aOperand == 0 )
       
   287                 {
       
   288                 iCCalcView->UpdateState( CCalcView::EOperator );
       
   289                 User::Leave(KErrDivideByZero); //  Error causes
       
   290                 }
       
   291             else
       
   292                 {
       
   293                 result /= aOperand;
       
   294                 }
       
   295             break;
       
   296             }
       
   297 		case TCalcEditLine::ECalcSqrt:
       
   298 			{
       
   299 			if ( aOperand < 0 )
       
   300 				{
       
   301                 User::Leave(KErrNotSupported); //  Error causes
       
   302                 }
       
   303 			else
       
   304 				Math::Sqrt(result, aOperand);
       
   305 			break;
       
   306 			}
       
   307 		case TCalcEditLine::ECalcPercent:
       
   308 			{
       
   309 			result = (result * aOperand) / 100;
       
   310 			break;
       
   311 			}
       
   312         case  TCalcEditLine::ECalcOperatorNone:
       
   313             {
       
   314             result = aOperand;
       
   315             break;
       
   316             }
       
   317         default:
       
   318             {
       
   319             break;
       
   320             }
       
   321         }
       
   322     //  Check Result. If overflow, Leave occurs.
       
   323     CheckResultL(&result);
       
   324 
       
   325     // Overflow do not occur
       
   326     return  result;
       
   327     }
       
   328 
       
   329 
       
   330 // ---------------------------------------------------------
       
   331 // CCalcDocument::CheckResultL
       
   332 // Check overflow and underflow  
       
   333 // Leave may occur, causes KErrOverflow.
       
   334 // (other items were commented in a header).
       
   335 // ---------------------------------------------------------
       
   336 //
       
   337 void CCalcDocument::CheckResultL
       
   338                    (TReal64* aResult)    
       
   339     {
       
   340     // Set data format 
       
   341     TRealFormat realFormat(KCalcMaxNumberWidth, KCalcMaxDigits);  
       
   342     if ( *aResult >= 0 )
       
   343         {
       
   344         realFormat.iWidth--;
       
   345         }
       
   346     realFormat.iType = KRealFormatNoExponent;
       
   347     realFormat.iTriLen = 0;  //  Delimit character is nothing
       
   348     TLocale locale;
       
   349     TChar separator(locale.DecimalSeparator());
       
   350     
       
   351     realFormat.iPoint = separator;
       
   352 
       
   353     TBuf<KCalcMaxNumberWidth> buffer;  
       
   354     TInt code = buffer.Num(*aResult, realFormat);
       
   355     
       
   356     if(KErrOverflow == code || KErrUnderflow == code)
       
   357 	    {
       
   358 	    TRealFormat realFormat(KCalcMaxNumberWidth);  
       
   359 	    if ( *aResult >= 0 )
       
   360 	        {
       
   361 	        realFormat.iWidth--;
       
   362 	        }
       
   363 	    realFormat.iType = KRealFormatExponent;
       
   364 	    realFormat.iPlaces = 3;
       
   365 	    realFormat.iTriLen = 0;  //  Delimit character is nothing
       
   366 	    TLocale locale;
       
   367 	    TChar separator(locale.DecimalSeparator());
       
   368 	    
       
   369 	    realFormat.iPoint = separator;
       
   370 
       
   371 	    TBuf<KCalcMaxNumberWidth> buffer;  
       
   372 	    code = buffer.Num(*aResult, realFormat);
       
   373 	    }
       
   374 	
       
   375 	switch (code)
       
   376         {
       
   377         case KErrOverflow:
       
   378             {
       
   379             User::Leave(KErrOverflow);  
       
   380             break;
       
   381             }
       
   382         case KErrUnderflow:
       
   383             {
       
   384             *aResult = 0.0;
       
   385             break;
       
   386             }
       
   387         default:
       
   388             {
       
   389             break;
       
   390             }
       
   391         }
       
   392    
       
   393     }
       
   394 
       
   395 
       
   396 // ---------------------------------------------------------
       
   397 // CCalcDocument::ExternalizeL
       
   398 // Externalising of the last result and memory.
       
   399 // (other items were commented in a header).
       
   400 // ---------------------------------------------------------
       
   401 //
       
   402 void CCalcDocument::ExternalizeL
       
   403         (RWriteStream& aStream) const 
       
   404     {
       
   405     aStream.WriteReal64L(iLastResult);  // Write last result
       
   406     aStream.WriteReal64L(iMemory);      // Write memory
       
   407     }
       
   408 
       
   409 // ---------------------------------------------------------
       
   410 // CCalcDocument::InternalizeL
       
   411 // Internalising of the last result and memory.
       
   412 // (other items were commented in a header).
       
   413 // ---------------------------------------------------------
       
   414 //
       
   415 void CCalcDocument::InternalizeL
       
   416         (RReadStream& aStream) 
       
   417     {
       
   418     iLastResult = aStream.ReadReal64L();    // Read last result
       
   419     iMemory = aStream.ReadReal64L();        // Read memory
       
   420 
       
   421     // If read value is out of range, 
       
   422     // memory is replaced to default one.
       
   423     TRAPD(error, CheckResultL(&iMemory));
       
   424     if (error == KErrOverflow)
       
   425         {
       
   426         iMemory = KCalcDefaultMemory;
       
   427         }
       
   428 
       
   429     // If read value is out of range, 
       
   430     // last result is replaced to default one.
       
   431     TRAP(error, CheckResultL(&iLastResult));
       
   432     if (error == KErrOverflow)
       
   433         {
       
   434         iLastResult = KCalcDefaultLastResult;
       
   435         }
       
   436 
       
   437     }
       
   438 
       
   439 // ---------------------------------------------------------
       
   440 // CCalcDocument::CreateAppUiL
       
   441 // This function is called when Calculator application is opened. 
       
   442 // (other items were commented in a header).
       
   443 // ---------------------------------------------------------
       
   444 //
       
   445 CEikAppUi* CCalcDocument::CreateAppUiL()
       
   446     {
       
   447     return new (ELeave) CCalcAppUi;
       
   448     }
       
   449 
       
   450 // ---------------------------------------------------------
       
   451 // CCalcDocument::SaveStateL
       
   452 // Store memory and last result
       
   453 // (other items were commented in a header).
       
   454 // ---------------------------------------------------------
       
   455 //
       
   456 void CCalcDocument::SaveStateL()
       
   457 {
       
   458 		RFileWriteStream out;
       
   459 		RFs fileSession;
       
   460 			
       
   461 		User::LeaveIfError(fileSession.Connect());
       
   462     	CleanupClosePushL(fileSession);
       
   463     
       
   464     	TFileName filePath;
       
   465 		TBuf<1> tempDes;
       
   466 		TChar driveChar;
       
   467 	   	
       
   468     	User::LeaveIfError(fileSession.PrivatePath(filePath));
       
   469     	fileSession.DriveToChar(KDefaultDrive, driveChar);
       
   470     	tempDes.Append(driveChar);
       
   471     	filePath.Insert(0,KDelimiter);
       
   472     	filePath.Insert(0,tempDes);
       
   473     	filePath.Append(KCalculatorFilename);
       
   474     	
       
   475     	TInt err( out.Replace( fileSession, filePath,EFileWrite ) );
       
   476 	
       
   477 	if( !err )
       
   478 		{
       
   479 		TRAP( err, ExternalizeL( out ) );
       
   480 	
       
   481 		out.Close();
       
   482 		}
       
   483 		  
       
   484   	CleanupStack::PopAndDestroy();
       
   485   		
       
   486 }
       
   487 
       
   488  // ---------------------------------------------------------
       
   489 // CCalcDocument::LoadStateL
       
   490 // Restore memory and last result
       
   491 // This function is called when document file exists. 
       
   492 // (other items were commented in a header).
       
   493 // ---------------------------------------------------------
       
   494 //   
       
   495     void CCalcDocument::LoadStateL()
       
   496     {
       
   497     	RFileReadStream in;
       
   498     	RFs fileSession;
       
   499     		
       
   500     	User::LeaveIfError(fileSession.Connect());
       
   501     	CleanupClosePushL(fileSession);
       
   502 
       
   503 		TFileName filePath;
       
   504 		TBuf<1> tempDes;
       
   505 		TChar driveChar;
       
   506     	User::LeaveIfError(fileSession.PrivatePath(filePath));
       
   507     	fileSession.DriveToChar(KDefaultDrive, driveChar);
       
   508     	tempDes.Append(driveChar);
       
   509     	filePath.Insert(0,KDelimiter);
       
   510     	filePath.Insert(0,tempDes);
       
   511     	filePath.Append(KCalculatorFilename);
       
   512   		
       
   513 		TInt err( in.Open( fileSession, filePath,
       
   514 			EFileRead ) );
       
   515 
       
   516 	if( !err )
       
   517 		{
       
   518 		TRAPD(readErr,InternalizeL( in ) );
       
   519 		
       
   520 		if ( readErr )
       
   521         {
       
   522         // Internalizing fails.
       
   523         iMemory = KCalcDefaultMemory;         // Reset memoey
       
   524         iLastResult = KCalcDefaultLastResult; // Reset last result
       
   525         }
       
   526         
       
   527 		in.Close();
       
   528 		}
       
   529 			CleanupStack::PopAndDestroy();
       
   530 		
       
   531         SetChanged(EFalse);
       
   532 	
       
   533     }
       
   534 
       
   535 // ---------------------------------------------------------
       
   536 // CCalcDocument::SetAppEnv
       
   537 // This function is used to receive a pointer to the
       
   538 // CCalcAppEnv.
       
   539 // (other items were commented in a header).
       
   540 // ---------------------------------------------------------
       
   541 //
       
   542 void CCalcDocument::SetAppEnv(CCalcAppEnv* aCalcAppEnv)
       
   543 	{
       
   544 		iCalcAppEnv = aCalcAppEnv;
       
   545 	}
       
   546 
       
   547 // ---------------------------------------------------------
       
   548 // CCalcDocument::SetCalcView
       
   549 // This function is used to receive a pointer to the
       
   550 // SetCalcView.
       
   551 // (other items were commented in a header).
       
   552 // ---------------------------------------------------------
       
   553 //
       
   554 void CCalcDocument::SetCalcView( CCalcView* aCCalcView )
       
   555     {
       
   556     iCCalcView = aCCalcView;
       
   557     }
       
   558 //  End of File