/*
 * calc.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 */

#include <vdr/plugin.h>
#include <stdlib.h>  // for system

static const char *VERSION        = "0.0.1-rc5";
static const char *DESCRIPTION    = "VDR mini calculator";
static const char *MAINMENUENTRY  = "Calc";

// --- cCalcMain -------------------------------------------------------------

enum operType {
  none,
  plus,
  minus,
  multiply,
  divide
  };

enum gradType {
  deg,
  rad,
  grad
  };

class cCalcMain : public cOsdObject {
private:
#if VDRVERSNUM<10300
  cOsdBase *osd;
#else
  cOsd     *osd;
#endif

  int x;
  int y;

  int operatorSet;  // 0 : plus, minus, multiply, divide
                        // 1: +/-, comma, C, AC
			// 2: M+, MC,

  bool operatorEntered; // TRUE wenn ein Operator schon eingegeben ist
                        // z.b. 2 + 3
			// die nächste Operation wäre z.B. +5, daher muss 2+3 schon mal ausgerechnet
			// und ausgegeben werden

  bool clearOutputForNextDigit;

#define MAX_DIGITS 100  // don?t reduce this...its safer!!!!!!

#if VDRVERSNUM<10300
  eDvbColor color;
#else
  tColor    color;
#endif

  char outputLine[MAX_DIGITS]; // line of the digits

  char operandLine1[MAX_DIGITS];
  char operandLine2[MAX_DIGITS];
  char cResult[MAX_DIGITS];
  char memoryLine[MAX_DIGITS];

  gradType eGradType;

  bool memorySet;

  void AddDigit(eKeys key);
  void CalculateResult(char* inOperand1, char* inOperand2, char *outOperand, char cOperator);
  operType operatorSymbol;
  void CalculateResultTrig(char* inOperand1, char *outOperand, char cOperator, gradType calculateGradType);
public:
  cCalcMain(void);
  ~cCalcMain();
  virtual void Show(void);
  virtual eOSState ProcessKey(eKeys Key);
  void UpdateDisplay(void);
  };

cCalcMain::cCalcMain(void)
{
  osd = NULL;
  x = y = 50;
  color = clrRed;
  clearOutputForNextDigit = false;
  operatorSet = 0;
  operatorEntered = false;
  memorySet = false;
  sprintf(outputLine,"");
  sprintf(operandLine1,"");
  sprintf(operandLine2,"");
  sprintf(cResult,"");
  sprintf(memoryLine,"");

  eGradType = deg;
}

cCalcMain::~cCalcMain()
{
  delete osd;
}

void cCalcMain::Show(void)
{
#if VDRVERSNUM<10300
  osd = cOsd::OpenRaw(50, 50); // offset of left,upper corner
  outputLine[0] = 0;
  if (osd) {
     osd->Create(0, 0, 400, 300, 4);
     osd->SetFont(fontFix);
     osd->AddColor(clrBackground);
     osd->AddColor(clrRed);
     osd->AddColor(clrGreen);
     osd->AddColor(clrYellow);
     osd->AddColor(clrBlue);
     osd->AddColor(clrBlack);
     osd->Clear();
     osd->Flush();
     UpdateDisplay();
  }
#endif
#if VDRVERSNUM>=10300
  osd = cOsdProvider::NewOsd(50, 50);
  if (osd) {
     tArea Area = { 0, 0, 399, 299,  4 };
     osd->SetAreas(&Area, 1);
     osd->DrawRectangle(0, 0, 399, 299, clrGray50);
     osd->Flush();
     UpdateDisplay();
       }

#endif
}

eOSState cCalcMain::ProcessKey(eKeys Key)
{
  eOSState state = cOsdObject::ProcessKey(Key);

  if (state == osUnknown) {
     switch (Key & ~k_Repeat) {
      case k0 ... k9:
         AddDigit(Key);
         break;
//       case kUp:     if (y > 0)   y--; break;
//       case kDown:   if (y < 196) y++; break;
       case kUp:   if (operatorSet == 1)
                       {
		         operatorSet = 0;
		       }
		   if (operatorSet == 2)
                       {
		         operatorSet = 1;
		       }
                   if (operatorSet == 3)
		       {
		         operatorSet = 2;
		       }
		   if (operatorSet == 4)
		       {
		         operatorSet = 3;
		       }
		       UpdateDisplay();
		   break;
       case kDown:
              	       if (operatorSet == 3)
       		       {
		         operatorSet = 4;
       		       }
        	       if (operatorSet == 2)
       		       {
		         operatorSet = 3;
       		       }

                       if (operatorSet == 1)
                       {
		         operatorSet = 2;
		       }
       		       if (operatorSet == 0)
                       {
		         operatorSet = 1;
		       }

		     UpdateDisplay();
		       break;
       case kRed:
         if (operatorSet == 0)
	 {
	   if (operatorEntered == true)
	   {
	     switch(operatorSymbol)
	     {
	       case(plus):
		CalculateResult(operandLine1,outputLine,cResult,'+');
		strcpy(operandLine1,cResult);
	        break;
	       case(minus):
		CalculateResult(operandLine1,outputLine,cResult,'-');
		strcpy(operandLine1,cResult);
	        break;
	       case(multiply):
		CalculateResult(operandLine1,outputLine,cResult,'*');
		strcpy(operandLine1,cResult);
	        break;
               case(divide):
		CalculateResult(operandLine1,outputLine,cResult,'/');
		strcpy(operandLine1,cResult);
	        break;
	       case(none):
	        break;
	     }
	     strcpy(outputLine,cResult);
	     UpdateDisplay();
	   }
	   else
	   {
	     strcpy(operandLine1, outputLine);
	   }
	   operatorSymbol = plus;
           clearOutputForNextDigit = true;
           UpdateDisplay();
	   operatorEntered = true;
	   break;
	 }
	 if (operatorSet == 1)
	 {
            CalculateResult(outputLine,"-1",cResult,'*');
	    strcpy(outputLine, cResult);
	    UpdateDisplay();
	    break;
	 }
	 if (operatorSet == 2)
	 {
	    strcpy(memoryLine,outputLine );
	    UpdateDisplay();
	    break;
	 }
	 if (operatorSet == 3)
	 {
	    eGradType = deg;
	    UpdateDisplay();
	    break;
	 }
	 if (operatorSet == 4)
	 {
	   CalculateResultTrig(outputLine,cResult,'s',eGradType);
	   strcpy(outputLine, cResult);
	   UpdateDisplay();
	   break;
	 }
	 break;
       case kGreen:
         if (operatorSet == 0)
	 {
	   if (operatorEntered == true)
	   {
	     switch(operatorSymbol)
	     {
	       case(plus):
		CalculateResult(operandLine1,outputLine,cResult,'+');
		strcpy(operandLine1,cResult);
	        break;
	       case(minus):
		CalculateResult(operandLine1,outputLine,cResult,'-');
		strcpy(operandLine1,cResult);
	        break;
	       case(multiply):
		CalculateResult(operandLine1,outputLine,cResult,'*');
		strcpy(operandLine1,cResult);
	        break;
               case(divide):
		CalculateResult(operandLine1,outputLine,cResult,'/');
		strcpy(operandLine1,cResult);
	        break;
	       case(none):
	        break;
	     }
	     strcpy(outputLine,cResult);
	     UpdateDisplay();
	     break;
	   }
	   else
	   {
	     strcpy(operandLine1, outputLine);
	   }
	   operatorSymbol = minus;
           clearOutputForNextDigit = true;
           UpdateDisplay();
	   operatorEntered = true;
	   break;
	 }
	 if (operatorSet == 1)
	 {
	   if (strchr(outputLine,'.') == NULL)
	   sprintf(outputLine,"%s.",outputLine);
           UpdateDisplay();
	   break;
	 }
	 if (operatorSet == 2)
	 {
	    sprintf(memoryLine,"");
	    memorySet = false;
	    UpdateDisplay();
	    break;
	 }
	 if (operatorSet == 3)
	 {
	    eGradType = rad;
	    UpdateDisplay();
    	    break;
	 }
	 if (operatorSet == 4)
	 {
	   CalculateResultTrig(outputLine,cResult,'c',eGradType);
	   strcpy(outputLine, cResult);
	   UpdateDisplay();
	   break;
	 }
       case kYellow:
         if (operatorSet == 0)
	 {
	   if (operatorEntered == true)
	   {
	     switch(operatorSymbol)
	     {
	       case(plus):
		CalculateResult(operandLine1,outputLine,cResult,'+');
		strcpy(operandLine1,cResult);
	        break;
	       case(minus):
		CalculateResult(operandLine1,outputLine,cResult,'-');
		strcpy(operandLine1,cResult);
	        break;
	       case(multiply):
		CalculateResult(operandLine1,outputLine,cResult,'*');
		strcpy(operandLine1,cResult);
	        break;
               case(divide):
		CalculateResult(operandLine1,outputLine,cResult,'/');
		strcpy(operandLine1,cResult);
	        break;
	       case(none):
	        break;
	     }
	     strcpy(outputLine,cResult);
	     UpdateDisplay();
	     break;
	   }
	   else
	   {
	     strcpy(operandLine1, outputLine);
	   }
	   operatorSymbol = multiply;
           clearOutputForNextDigit = true;
           UpdateDisplay();
	   operatorEntered = true;
	   break;
	 }
	 if (operatorSet == 1)  // Clear
	 {
           sprintf(outputLine,"");
	   clearOutputForNextDigit = false;
	   UpdateDisplay();
	   break;
	 }
	 if (operatorSet == 2)
	 {
	    strcpy(outputLine,memoryLine);
	    UpdateDisplay();
	    break;
	 }
	 if (operatorSet == 3)
	 {
	    eGradType = grad;
	    UpdateDisplay();
	    break;
	 }
	 if (operatorSet == 4)
	 {
	   CalculateResultTrig(outputLine,cResult,'t',eGradType);
	   strcpy(outputLine, cResult);
	   UpdateDisplay();
	   break;
	 }
       case kBlue:
         if (operatorSet == 0)
	 {
	   if (operatorEntered == true)
	   {
	     switch(operatorSymbol)
	     {
	       case(plus):
		CalculateResult(operandLine1,outputLine,cResult,'+');
		strcpy(operandLine1,cResult);
	        break;
	       case(minus):
		CalculateResult(operandLine1,outputLine,cResult,'-');
		strcpy(operandLine1,cResult);
	        break;
	       case(multiply):
		CalculateResult(operandLine1,outputLine,cResult,'*');
		strcpy(operandLine1,cResult);
	        break;
               case(divide):
		CalculateResult(operandLine1,outputLine,cResult,'/');
		strcpy(operandLine1,cResult);
	        break;
	       case(none):
	        break;
	     }
	     strcpy(outputLine,cResult);
	     UpdateDisplay();
	     break;
	   }
	   else
	   {
	     strcpy(operandLine1, outputLine);
	   }
	   operatorSymbol = divide;
           clearOutputForNextDigit = true;
           UpdateDisplay();
	   operatorEntered = true;
	   break;
	 }
	 if (operatorSet == 1)  // Clear All
	 {
           sprintf(outputLine,"");
	   operatorSymbol = none;
	   clearOutputForNextDigit = false;
	   UpdateDisplay();
	   break;
	 }
	 if (operatorSet == 4) //pi
	 {
	   sprintf(outputLine,"3.1415926535");
	   UpdateDisplay();
	   break;
	 }
       case kBack:
         return osEnd;
       case kMenu:
         return osEnd;
       case kOk:
       if (operatorSymbol != none)
       {
	 operatorEntered = false;
	 switch(operatorSymbol)
	 {
	   case(plus):
	     CalculateResult(operandLine1,outputLine,cResult,'+');
	     break;
	   case(minus):
	     CalculateResult(operandLine1,outputLine,cResult,'-');
	     break;
	   case(multiply):
	     CalculateResult(operandLine1,outputLine,cResult,'*');
	     break;
           case(divide):
	     CalculateResult(operandLine1,outputLine,cResult,'/');
	     break;
	   case(none):
	     break;
	 }

	 strcpy(outputLine,cResult);
//	printf("outputLine %s\n",outputLine);
	 clearOutputForNextDigit = true;
         operatorSymbol = none;
	}
	 UpdateDisplay();
         break;

       default: return state;
       }
     osd->Flush();
     state = osContinue;
     }
  return state;
}


void cCalcMain::CalculateResult(char* inOperand1, char* inOperand2, char *outOperand, char cOperator)
{
  FILE *f;
//  printf("inOperand1 %s inOperand2 %s operator %c\n",inOperand1,inOperand2,cOperator);
  f = fopen("./bc_in.dat","w");
  fprintf(f,"scale = 10\n");
  fprintf(f,"%s%c%s\n",inOperand1,cOperator,inOperand2);
  fclose(f);
  system("bc <./bc_in.dat >./bc_out.dat");
  f = fopen("./bc_out.dat","r");
  if (f != NULL)
  {
    fscanf(f,"%s",outOperand);
    fclose(f);
  }
    else
    printf("VDR-Calc : bc run failed !!\n");
}

void cCalcMain::CalculateResultTrig(char* inOperand1, char *outOperand, char cOperator, gradType 				calculateGradType)
{
  FILE *f;


  if (calculateGradType == deg)
    CalculateResult(inOperand1, "(3.1415926535/180)",inOperand1, '*');
  if (calculateGradType == grad)
    CalculateResult(inOperand1, "(3.1415926535/200)",inOperand1, '*');

//  printf("inOperand1 %s inOperand2 %s operator %c\n",inOperand1,inOperand2,cOperator);
  f = fopen("./bc_in.dat","w");
  fprintf(f,"scale = 10\n");

// only valid for cOperator == s, c, t (for sin,cos,tan)
  if ((cOperator == 's') || (cOperator == 'c'))
  {
    fprintf(f,"%c(%s)\n",cOperator, inOperand1);
  }
  if (cOperator == 't')
  {
    fprintf(f,"s(%s)/c(%s)\n",inOperand1,inOperand1);
  }
  fclose(f);
  system("bc -l <./bc_in.dat >./bc_out.dat");
  f = fopen("./bc_out.dat","r");
  if (f != NULL)
  {
    fscanf(f,"%s",outOperand);
    fclose(f);
  }
    else
    printf("VDR-Calc : bc run failed !!\n");
  clearOutputForNextDigit = true;
}

void cCalcMain::UpdateDisplay(void)
{

int stepx = 90;
#define yPos  100
#define yStep 35
#if VDRVERSNUM<10300
  if (osd)
  {
    osd->Clear();
    osd->Fill(10, 50, 350, 40, clrBlack);
    osd->Text(10,0,"VDRCalc 0.0.1",clrYellow);

    osd->Text(20,30,"                         ",clrRed,clrBlack);
    osd->Text(20,60,"                         ",clrRed,clrBlack);
    osd->Text(20,50,"                         ",clrRed,clrBlack);
    osd->Text(30,50,outputLine,clrYellow,clrBlack);
    //
    osd->Text(0,yPos," ",clrWhite,clrBackground);
    osd->Text(0,yPos+yStep," ",clrWhite,clrBackground);
    osd->Text(0,yPos+2*yStep," ",clrWhite,clrBackground);


    osd->Text(30,yPos," + ",clrBlack,clrRed);
    osd->Text(30+stepx,yPos," - ",clrBlack,clrGreen);
    osd->Text(30+2*stepx,yPos," * ",clrBlack,clrYellow);
    osd->Text(30+3*stepx,yPos," / ",clrBlack,clrBlue);
    if (operatorSet == 0)
      osd->Text(0,yPos,">",clrWhite,clrBlue);

    osd->Text(30,yPos+yStep,"+/-",clrBlack,clrRed);
    osd->Text(30+stepx,yPos+yStep," , ",clrBlack,clrGreen);
    osd->Text(30+2*stepx,yPos+yStep," C ",clrBlack,clrYellow);
    osd->Text(30+3*stepx,yPos+yStep," AC",clrBlack,clrBlue);
    if (operatorSet == 1)
      osd->Text(0,yPos+yStep,">",clrWhite,clrBlue);


    osd->Text(30,yPos+2*yStep,"MIn",clrBlack,clrRed);
    osd->Text(30+stepx,yPos+2*yStep,"MC ",clrBlack,clrGreen);
    osd->Text(30+2*stepx,yPos+2*yStep,"MR ",clrBlack,clrYellow);
    osd->Text(30+3*stepx,yPos+2*yStep,"   ",clrBlack,clrBlue);
    if (operatorSet == 2)
      osd->Text(0,yPos+2*yStep,">",clrWhite,clrBlue);

    if (eGradType == deg)
      osd->Text(30,yPos+3*yStep,"Deg",clrWhite,clrRed);
    else
      osd->Text(30,yPos+3*yStep,"Deg",clrBlack,clrRed);
    if (eGradType == rad)
    {
      osd->Text(30+stepx,yPos+3*yStep,"Rad",clrWhite,clrGreen);
    }
    else
      osd->Text(30+stepx,yPos+3*yStep,"Rad",clrBlack,clrGreen);
    if (eGradType == grad)
      osd->Text(30+2*stepx,yPos+3*yStep,"Gra",clrWhite,clrYellow);
    else
      osd->Text(30+2*stepx,yPos+3*yStep,"Gra",clrBlack,clrYellow);
    osd->Text(30+3*stepx,yPos+3*yStep,"   ",clrBlack,clrBlue);
    if (operatorSet == 3)
      osd->Text(0,yPos+3*yStep,">",clrWhite,clrBlue);

    osd->Text(30,yPos+4*yStep,"Sin",clrBlack,clrRed);
    osd->Text(30+stepx,yPos+4*yStep,"Cos",clrBlack,clrGreen);
    osd->Text(30+2*stepx,yPos+4*yStep,"Tan",clrBlack,clrYellow);
    osd->Text(30+3*stepx,yPos+4*yStep,"Pi ",clrBlack,clrBlue);
    if (operatorSet == 4)
      osd->Text(0,yPos+4*yStep,">",clrWhite,clrBlue);

//printf("output line %s*\n",outputLine);
    switch(operatorSymbol)
    {
    case(plus):
      osd->Text(yPos,10,"+",clrRed);
      break;
    case(minus):
      osd->Text(yPos,10,"-",clrRed);
      break;
    case(multiply):
      osd->Text(yPos,10,"*",clrRed);
      break;
    case(divide):
      osd->Text(yPos,10,"/",clrRed);
      break;
    case(none):
      break;
    }
    if (memorySet == true)
      osd->Text(100,100,"M",clrRed);
    osd->Flush();
  }
#endif


#if VDRVERSNUM>=10300
  if (osd)
  {
 //   osd->Clear();
    osd->DrawRectangle(10, 50, 350, 40, (unsigned int)clrBlack);
    osd->DrawText(10,0,"VDRCalc 0.0.1",(unsigned int)clrYellow,(unsigned int)clrGray50, cFont::GetFont(fontFix));

    osd->DrawText(20,30,"                         ",(unsigned int)clrRed,(unsigned int)clrBlack, cFont::GetFont(fontFix));
    osd->DrawText(20,60,"                         ",(unsigned int)clrRed,(unsigned int)clrBlack, cFont::GetFont(fontFix));
    osd->DrawText(20,50,"                         ",(unsigned int)clrRed,(unsigned int)clrBlack, cFont::GetFont(fontFix));
    osd->DrawText(30,50,outputLine,(unsigned int)clrYellow,(unsigned int)clrBlack, cFont::GetFont(fontFix));

    osd->DrawText(0,yPos," ",(unsigned int)clrWhite,(unsigned int)clrGray50, cFont::GetFont(fontFix));
    osd->DrawText(30,yPos," + ",(unsigned int)clrBlack,(unsigned int)clrRed, cFont::GetFont(fontFix));
    osd->DrawText(30+stepx,yPos," - ",(unsigned int)clrBlack,(unsigned int)clrGreen, cFont::GetFont(fontFix));
    osd->DrawText(30+2*stepx,yPos," * ",(unsigned int)clrBlack,(unsigned int)clrYellow, cFont::GetFont(fontFix));
    osd->DrawText(30+3*stepx,yPos," / ",(unsigned int)clrBlack,(unsigned int)clrBlue, cFont::GetFont(fontFix));
    osd->DrawText(0,yPos," ",(unsigned int)clrWhite,(unsigned int)clrGray50, cFont::GetFont(fontFix));
    osd->DrawText(0,yPos+yStep," ",(unsigned int)clrWhite,(unsigned int)clrGray50, cFont::GetFont(fontFix));
    osd->DrawText(0,yPos+2*yStep," ",(unsigned int)clrWhite,(unsigned int)clrGray50, cFont::GetFont(fontFix));
    osd->DrawText(0,yPos+3*yStep," ",(unsigned int)clrWhite,(unsigned int)clrGray50, cFont::GetFont(fontFix));
    osd->DrawText(0,yPos+4*yStep," ",(unsigned int)clrWhite,(unsigned int)clrGray50, cFont::GetFont(fontFix));

    if (operatorSet == 0)
    {
      osd->DrawText(0,yPos,">",(unsigned int)clrWhite,(unsigned int)clrBlue, cFont::GetFont(fontFix));
    }

    osd->DrawText(30,yPos+yStep,"+/-",(unsigned int)clrBlack,(unsigned int)clrRed, cFont::GetFont(fontFix));
    osd->DrawText(30+stepx,yPos+yStep," , ",(unsigned int)clrBlack,(unsigned int)clrGreen, cFont::GetFont(fontFix));
    osd->DrawText(30+2*stepx,yPos+yStep," C ",(unsigned int)clrBlack,(unsigned int)clrYellow, cFont::GetFont(fontFix));
    osd->DrawText(30+3*stepx,yPos+yStep," AC",(unsigned int)clrBlack,(unsigned int)clrBlue, cFont::GetFont(fontFix));
    if (operatorSet == 1)
    {
      osd->DrawText(0,yPos+yStep,">",clrWhite,clrBlue, cFont::GetFont(fontFix));
    }

    osd->DrawText(30,yPos+2*yStep,"MIn",(unsigned int)clrBlack,(unsigned int)clrRed, cFont::GetFont(fontFix));
    osd->DrawText(30+stepx,yPos+2*yStep,"MC ",(unsigned int)clrBlack,(unsigned int)clrGreen, cFont::GetFont(fontFix));
    osd->DrawText(30+2*stepx,yPos+2*yStep,"MR ",(unsigned int)clrBlack,(unsigned int)clrYellow, cFont::GetFont(fontFix));
    osd->DrawText(30+3*stepx,yPos+2*yStep,"   ",(unsigned int)clrBlack, (unsigned int)clrBlue, cFont::GetFont(fontFix));

    if (operatorSet == 2)
    {
      osd->DrawText(0,yPos+2*yStep,">",clrWhite,clrBlue, cFont::GetFont(fontFix));
    }
    if (eGradType == deg)
      	osd->DrawText(30,yPos+3*yStep,"Deg",(unsigned int)clrWhite,(unsigned int)clrRed, cFont::GetFont(fontFix));
    else
	osd->DrawText(30,yPos+3*yStep,"Deg",(unsigned int)clrBlack,(unsigned int)clrRed, cFont::GetFont(fontFix));
    if (eGradType == rad)
    	osd->DrawText(30+stepx,yPos+3*yStep,"Rad",(unsigned int)clrWhite,(unsigned int)clrGreen, cFont::GetFont(fontFix));
    else
    	osd->DrawText(30+stepx,yPos+3*yStep,"Rad",(unsigned int)clrBlack,(unsigned int)clrGreen, cFont::GetFont(fontFix));
    if (eGradType == grad)
      osd->DrawText(30+2*stepx,yPos+3*yStep,"Gra",(unsigned int)clrWhite,(unsigned int)clrYellow, cFont::GetFont(fontFix));
    else
      osd->DrawText(30+2*stepx,yPos+3*yStep,"Gra",(unsigned int)clrBlack,(unsigned int)clrYellow, cFont::GetFont(fontFix));
    osd->DrawText(30+3*stepx,yPos+3*yStep,"   ",(unsigned int)clrBlack, (unsigned int)clrBlue, cFont::GetFont(fontFix));

    if (operatorSet == 3)
    {
      osd->DrawText(0,yPos+3*yStep,">",clrWhite,clrBlue, cFont::GetFont(fontFix));
    }


    osd->DrawText(30,yPos+4*yStep,"Sin",(unsigned int)clrBlack,(unsigned int)clrRed, cFont::GetFont(fontFix));
    osd->DrawText(30+stepx,yPos+4*yStep,"Cos",(unsigned int)clrBlack,(unsigned int)clrGreen, cFont::GetFont(fontFix));
    osd->DrawText(30+2*stepx,yPos+4*yStep,"Tan",(unsigned int)clrBlack,(unsigned int)clrYellow, cFont::GetFont(fontFix));
    osd->DrawText(30+3*stepx,yPos+4*yStep,"Pi ",(unsigned int)clrBlack, (unsigned int)clrBlue, cFont::GetFont(fontFix));

    if (operatorSet == 4)
    {
      osd->DrawText(0,yPos+4*yStep,">",clrWhite,clrBlue, cFont::GetFont(fontFix));
    }
//printf("output line %s*\n",outputLine);
    switch(operatorSymbol)
    {
    case(plus):
      osd->DrawText(yPos,100,"+",(unsigned int)clrRed, (unsigned int)clrGray50, cFont::GetFont(fontFix));
      break;
    case(minus):
      osd->DrawText(yPos,100,"-",(unsigned int)clrRed, (unsigned int)clrGray50, cFont::GetFont(fontFix));
      break;
    case(multiply):
      osd->DrawText(yPos,100,"*",(unsigned int)clrRed, (unsigned int)clrGray50, cFont::GetFont(fontFix));
      break;
    case(divide):
      osd->DrawText(yPos,100,"/",(unsigned int)clrRed, (unsigned int)clrGray50, cFont::GetFont(fontFix));
      break;
    case(none):
      break;
    }
    if (memorySet == true)
      osd->DrawText(100,100,"M",(unsigned int)clrRed, (unsigned int)clrGray50,cFont::GetFont(fontFix));
    osd->Flush();
  }
#endif
}

void cCalcMain::AddDigit(eKeys key)
{
  if   (clearOutputForNextDigit == true)
  {
    //printf("clear...\n");
    clearOutputForNextDigit = false;
    outputLine[0] = 0;
    sprintf(outputLine,"%s","                                                                             ");
    UpdateDisplay();
    outputLine[0] = 0;
  }
switch (key & ~k_Repeat) {
  case k0:
   	sprintf(outputLine,"%s0",outputLine);
	break;
  case k1:
  	sprintf(outputLine,"%s1",outputLine);
	break;
  case k2:
  	sprintf(outputLine,"%s2",outputLine);
	break;
  case k3:
   	sprintf(outputLine,"%s3",outputLine);
	break;
  case k4:
  	sprintf(outputLine,"%s4",outputLine);
	break;
  case k5:
  	sprintf(outputLine,"%s5",outputLine);
	break;
  case k6:
   	sprintf(outputLine,"%s6",outputLine);
	break;
  case k7:
   	sprintf(outputLine,"%s7",outputLine);
	break;
  case k8:
  	sprintf(outputLine,"%s8",outputLine);
	break;
  case k9:
  	sprintf(outputLine,"%s9",outputLine);
	break;

} // switch
  UpdateDisplay();
}

// --- CPluginCalc --------------------------------------------------------

class CPluginCalc : public cPlugin {
private:
  // Add any member variables or functions you may need here.
public:
  CPluginCalc(void);
  virtual ~CPluginCalc();
  virtual const char *Version(void) { return VERSION; }
  virtual const char *Description(void) { return DESCRIPTION; }
  virtual const char *CommandLineHelp(void);
  virtual bool ProcessArgs(int argc, char *argv[]);
  virtual bool Start(void);
  virtual void Housekeeping(void);
  virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
  virtual cOsdObject *MainMenuAction(void);
  virtual cMenuSetupPage *SetupMenu(void);
  virtual bool SetupParse(const char *Name, const char *Value);
  };

CPluginCalc::CPluginCalc(void)
{
  // Initialize any member variables here.
  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
}

CPluginCalc::~CPluginCalc()
{
  // Clean up after yourself!
}

const char *CPluginCalc::CommandLineHelp(void)
{
  // Return a string that describes all known command line options.
  return NULL;
}

bool CPluginCalc::ProcessArgs(int argc, char *argv[])
{
  // Implement command line argument processing here if applicable.
  return true;
}

bool CPluginCalc::Start(void)
{
  // Start any background activities the plugin shall perform.
  return true;
}

void CPluginCalc::Housekeeping(void)
{
  // Perform any cleanup or other regular tasks.
}

cOsdObject *CPluginCalc::MainMenuAction(void)
{
  // Perform the action when selected from the main VDR menu.
  return new cCalcMain;
}

cMenuSetupPage *CPluginCalc::SetupMenu(void)
{
  // Return a setup menu in case the plugin supports one.
  return NULL;
}

bool CPluginCalc::SetupParse(const char *Name, const char *Value)
{
  // Parse your own setup parameters and store their values.
  return false;
}

VDRPLUGINCREATOR(CPluginCalc); // Don't touch this!
