/*
 * skinclassic.c: The 'classic' VDR skin
 *
 * See the main source file 'vdr.c' for copyright information and
 * how to reach the author.
 *
 * $Id: skinclassic.c 1.11 2005/01/09 11:56:29 kls Exp $
 */

#include "skinsvenhelau.h"
#include "common.h"

#include <vdr/menu.h>
#include <vdr/font.h>
#include <vdr/i18n.h>
#include <vdr/osd.h>
#include <vdr/themes.h>
#include <../symbols/teletext.xpm>
#include <../symbols/audio.xpm>
#include <../symbols/dolbydigital.xpm>
#include <../symbols/encrypted.xpm>
#include <../symbols/recording.xpm>
#include <../symbols/radio.xpm>

#include <../symbols/frew.xpm>
#include <../symbols/frew1.xpm>
#include <../symbols/frew2.xpm>
#include <../symbols/frew3.xpm>
#include <../symbols/srew.xpm>
#include <../symbols/srew1.xpm>
#include <../symbols/srew2.xpm>
#include <../symbols/srew3.xpm>
#include <../symbols/pause.xpm>
#include <../symbols/play.xpm>
#include <../symbols/sfwd.xpm>
#include <../symbols/sfwd1.xpm>
#include <../symbols/sfwd2.xpm>
#include <../symbols/sfwd3.xpm>
#include <../symbols/ffwd.xpm>
#include <../symbols/ffwd1.xpm>
#include <../symbols/ffwd2.xpm>
#include <../symbols/ffwd3.xpm>

#define ScrollWidth  5
#define EMCOLOR_BACKGROUND		clrBlack
#define EMCOLOR_BACKGROUND2		clrGray50

static cTheme Theme4col;

THEME_CLR(Theme4col, clrButtonGreenFgNew,         clrBlack);
THEME_CLR(Theme4col, clrButtonYellowFgNew,        clrBlack);
THEME_CLR(Theme4col, clrButtonBlueFgNew,          clrBlack);
THEME_CLR(Theme4col, clrButtonRedFgNew,           clrBlack);
THEME_CLR(Theme4col, clrChannelEpgTimeBgNew,      clrRed);
THEME_CLR(Theme4col, clrChannelBackgroundNew,     clrGray50);
THEME_CLR(Theme4col, clrVolumePromptNew,          clrCyan);
THEME_CLR(Theme4col, clrVolumeBarUpperNew,        clrWhite);
THEME_CLR(Theme4col, clrVolumeBarLowerNew,        clrCyan);
THEME_CLR(Theme4col, clrVolumeBackgroundNew,      clrGray50);
THEME_CLR(Theme4col, clrMenuBackgroundNew,        clrGray50);
THEME_CLR(Theme4col, clrTracksBackgroundNew,      clrGray50);
THEME_CLR(Theme4col, clrReplayBackgroundNew,      clrGray50);
THEME_CLR(Theme4col, clrReplayProgressMarkNew,    clrRed);
THEME_CLR(Theme4col, clrReplayProgressCurrentNew, clrRed);
THEME_CLR(Theme4col, clrMessageNewFg,             clrBlack);
THEME_CLR(Theme4col, clrMessageNewBg,             clrCyan);

THEME_CLR(Theme4col, clrButtonGreenBgNew,         clrGreen);
THEME_CLR(Theme4col, clrButtonYellowBgNew,        clrYellow);
THEME_CLR(Theme4col, clrButtonRedBgNew,           clrRed);

THEME_CLR(Theme4col, clrBackground,               clrBlack);
THEME_CLR(Theme4col, clrButtonRedFg,              clrBlack);
THEME_CLR(Theme4col, clrButtonRedBg,              clrCyan);
THEME_CLR(Theme4col, clrButtonGreenFg,            clrBlack);
THEME_CLR(Theme4col, clrButtonYellowFg,           clrBlack);
THEME_CLR(Theme4col, clrButtonYellowBg,           clrCyan);
THEME_CLR(Theme4col, clrButtonBlueFg,             clrBlack);
THEME_CLR(Theme4col, clrButtonBlueBg,             clrCyan);
THEME_CLR(Theme4col, clrMessageStatusFg,          clrWhite);
THEME_CLR(Theme4col, clrMessageStatusBg,          clrCyan);
THEME_CLR(Theme4col, clrMessageInfoFg,            clrWhite);
THEME_CLR(Theme4col, clrMessageInfoBg,            clrCyan);
THEME_CLR(Theme4col, clrMessageWarningFg,         clrWhite);
THEME_CLR(Theme4col, clrMessageWarningBg,         clrCyan);
THEME_CLR(Theme4col, clrMessageErrorFg,           clrWhite);
THEME_CLR(Theme4col, clrMessageErrorBg,           clrCyan);
THEME_CLR(Theme4col, clrVolumePrompt,             clrCyan);
THEME_CLR(Theme4col, clrVolumeBarUpper,           clrCyan);
THEME_CLR(Theme4col, clrVolumeBarLower,           clrWhite);
THEME_CLR(Theme4col, clrChannelName,              clrWhite);
THEME_CLR(Theme4col, clrChannelDate,              clrWhite);
THEME_CLR(Theme4col, clrChannelEpgTimeFg,         clrWhite);
THEME_CLR(Theme4col, clrChannelEpgTimeBg,         clrRed);
THEME_CLR(Theme4col, clrChannelEpgTitle,          clrCyan);
THEME_CLR(Theme4col, clrChannelEpgShortText,      clrWhite);
THEME_CLR(Theme4col, clrMenuTitleFg,              clrBlack);
THEME_CLR(Theme4col, clrMenuTitleBg,              clrCyan);
THEME_CLR(Theme4col, clrMenuDate,                 clrBlack);
THEME_CLR(Theme4col, clrMenuItemCurrentFg,        clrBlack);
THEME_CLR(Theme4col, clrMenuItemCurrentBg,        clrCyan);
THEME_CLR(Theme4col, clrMenuItemSelectable,       clrWhite);
THEME_CLR(Theme4col, clrMenuItemNonSelectable,    clrCyan);
THEME_CLR(Theme4col, clrMenuEventTime,            clrWhite);
THEME_CLR(Theme4col, clrMenuEventVpsFg,           clrBlack);
THEME_CLR(Theme4col, clrMenuEventVpsBg,           clrWhite);
THEME_CLR(Theme4col, clrMenuEventTitle,           clrCyan);
THEME_CLR(Theme4col, clrMenuEventShortText,       clrWhite);
THEME_CLR(Theme4col, clrMenuEventDescription,     clrCyan);
THEME_CLR(Theme4col, clrMenuScrollbarTotal,       clrWhite);
THEME_CLR(Theme4col, clrMenuScrollbarShown,       clrCyan);
THEME_CLR(Theme4col, clrMenuText,                 clrWhite);
THEME_CLR(Theme4col, clrReplayTitle,              clrWhite);
THEME_CLR(Theme4col, clrReplayCurrent,            clrWhite);
THEME_CLR(Theme4col, clrReplayTotal,              clrWhite);
THEME_CLR(Theme4col, clrReplayModeJump,           clrWhite);
THEME_CLR(Theme4col, clrReplayProgressSeen,       clrCyan);
THEME_CLR(Theme4col, clrReplayProgressRest,       clrWhite);
THEME_CLR(Theme4col, clrReplayProgressSelected,   clrCyan);
THEME_CLR(Theme4col, clrReplayProgressMark,       clrGreen);
THEME_CLR(Theme4col, clrReplayProgressCurrent,    clrCyan);


// --- cSkinClassicDisplayChannel --------------------------------------------

class cSkinSvenHelauDisplayChannel : public cSkinDisplayChannel {
private:
   cOsd *osd;
   int lineHeight;
   int timeWidth;
   bool message;
   int OffsetArea2;
   static cBitmap bmTeletext, bmRadio, bmAudio, bmDolbyDigital, bmEncrypted, bmRecording;
public:
   cSkinSvenHelauDisplayChannel(bool WithInfo);
   virtual ~cSkinSvenHelauDisplayChannel();
   virtual void SetChannel(const cChannel *Channel, int Number);
   virtual void SetEvents(const cEvent *Present, const cEvent *Following);
   virtual void SetMessage(eMessageType Type, const char *Text);
   virtual void Flush(void);
};

cBitmap cSkinSvenHelauDisplayChannel::bmTeletext(teletext_xpm);
cBitmap cSkinSvenHelauDisplayChannel::bmRadio(radio_xpm);
cBitmap cSkinSvenHelauDisplayChannel::bmAudio(audio_xpm);
cBitmap cSkinSvenHelauDisplayChannel::bmDolbyDigital(dolbydigital_xpm);
cBitmap cSkinSvenHelauDisplayChannel::bmEncrypted(encrypted_xpm);
cBitmap cSkinSvenHelauDisplayChannel::bmRecording(recording_xpm);

cSkinSvenHelauDisplayChannel::cSkinSvenHelauDisplayChannel(bool WithInfo)
{
   int Lines = WithInfo ? 7 : 1;
   const cFont *font = cFont::GetFont(fontOsd);
   lineHeight = font->Height();
   message = false;
   osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - Lines * lineHeight));
   timeWidth = font->Width("00:00") + 4;
   OffsetArea2 = Setup.OSDHeight;
   tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, Lines * lineHeight - 1, 4 }};
   osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
   osd->DrawRectangle(0                        , 0             , osd->Width()    , osd->Height() - 1, 0x00FFFFFF);
   osd->DrawRectangle(0                        , 3 * lineHeight, osd->Width() - 1, 4 * lineHeight   , 0x77000066);
   osd->DrawRectangle(lineHeight               , 2 * lineHeight, osd->Width() - 1, 3 * lineHeight   , 0x77000066);
   osd->DrawEllipse  (osd->Width() - lineHeight, 1 * lineHeight, osd->Width() - 1, 2 * lineHeight   , 0x77000066, 1);

   osd->DrawRectangle(0                        , OffsetArea2                 , osd->Width()             , OffsetArea2 + 3 * lineHeight,  0x88000000);
   osd->DrawRectangle(lineHeight               , OffsetArea2 + 3 * lineHeight, osd->Width() - lineHeight, OffsetArea2 + 4 * lineHeight,  0x88000000);
   osd->DrawEllipse  (osd->Width() - lineHeight, OffsetArea2 + 3 * lineHeight, osd->Width() - 1         , OffsetArea2 + 4 * lineHeight, 0x88000000, 4);
}

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

void cSkinSvenHelauDisplayChannel::SetChannel(const cChannel *Channel, int Number)
{
   const cFont *font = cFont::GetFont(fontOsd);
   osd->DrawRectangle(lineHeight                            , 2 * lineHeight       , osd->Width() / 3 * 2                        , 3 * lineHeight, 0xCC2233CC);
   osd->DrawEllipse  (0                                     , 2 * lineHeight       , lineHeight                                  , 3 * lineHeight, 0xCC2233CC, 2);
   osd->DrawRectangle(osd->Width() / 3 * 2                  , int(2.5 * lineHeight), osd->Width() / 3 * 2 + int(1.8 * lineHeight), 3 * lineHeight, 0xCC2233CC);
   osd->DrawEllipse  (osd->Width() / 3 * 2                  , 2 * lineHeight       , osd->Width() / 3 * 2 + lineHeight           , 3 * lineHeight, 0xCC2233CC, 1);
   osd->DrawEllipse  (osd->Width() / 3 * 2 + int(lineHeight * .8), 2 * lineHeight  , osd->Width() / 3 * 2 + int(1.8 * lineHeight), 3 * lineHeight, 0x77000066, 3);
   osd->DrawText(lineHeight, 2 * lineHeight - 1, ChannelString(Channel, Number), 0xFFFFFFFF, 0xCC2233CC, cFont::GetFont(fontOsd), osd->Width() / 3 * 2 - lineHeight);

   bool rec = cRecordControls::Active();
   osd->DrawBitmap(osd->Width() - 6 * lineHeight, 2 * lineHeight, teletext_xpm    , Channel->Tpid()  ? 0xFFFFFFFF : 0xCC2233CC, 0x77000066);
   osd->DrawBitmap(osd->Width() - 5 * lineHeight, 2 * lineHeight, audio_xpm       , Channel->Apid(1) ? 0xFFFFFFFF : 0xCC2233CC, 0x77000066);
   osd->DrawBitmap(osd->Width() - 4 * lineHeight, 2 * lineHeight, dolbydigital_xpm, Channel->Dpid(0) ? 0xFFFFFFFF : 0xCC2233CC, 0x77000066);
   osd->DrawBitmap(osd->Width() - 3 * lineHeight, 2 * lineHeight, bmEncrypted     , Channel->Ca()    ? 0xFFFFFFFF : 0xCC2233CC, 0x77000066);
   osd->DrawBitmap(osd->Width() - 2 * lineHeight, 2 * lineHeight, bmRecording     , rec ? 0xFFFFFFFF : 0xCC2233CC, 0x77000066);

   if (false) {
      int logox = 64;
      int logoy = 48;
      if (font->Width(Channel->Name()) != 0 ) {
         cBitmap bmp(logox, logoy, 8);
         const char *ChannelID = Channel->GetChannelID().ToString();
         char *filename;

         asprintf(&filename, "%s%s%s", "/usr/local/etc/vdr/plugins/SkinSF/", ChannelID,".xpm");
         osd->DrawText(0, 0, filename, 0xFFFFFFFF, 0xCC2233CC, cFont::GetFont(fontOsd));
         if (bmp.LoadXpm(filename) && (bmp.Width() == logox) && (bmp.Height() == logoy)) {
            osd->DrawBitmap(0, 0, filename);
         }
         free(filename);
      }
   }
}

void cSkinSvenHelauDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following)
{
   osd->DrawRectangle(0         , OffsetArea2                 , timeWidth - 1, OffsetArea2 + 3 * lineHeight, 0xBBAA1111);
   osd->DrawRectangle(lineHeight, OffsetArea2 + 3 * lineHeight, timeWidth - 1, OffsetArea2 + 4 * lineHeight, 0xBBAA1111);
   osd->DrawEllipse  (0         , OffsetArea2 + 3 * lineHeight, lineHeight   , OffsetArea2 + 4 * lineHeight, 0xBBAA1111, 3);

   int duration = -1;
   for (int i = 0; i < 2; i++) {
      const cEvent *e = !i ? Present : Following;
      if (e) {
         if (i==0) duration= int(4 * lineHeight * difftime(time(NULL), e->StartTime()) / e->Duration() );
         osd->DrawText(             2, OffsetArea2 + (2 * i    ) * lineHeight, e->GetTimeString(), Theme4col.Color(clrChannelEpgTimeFg), 0xBBAA1111, cFont::GetFont(fontOsd));
         osd->DrawText(timeWidth + 20, OffsetArea2 + (2 * i    ) * lineHeight, e->Title()        , Theme4col.Color(clrChannelEpgTimeFg), 0x88000000, cFont::GetFont(fontOsd), osd->Width() - lineHeight - 20 - timeWidth);
         osd->DrawText(timeWidth + 20, OffsetArea2 + (2 * i + 1) * lineHeight, e->ShortText()    , Theme4col.Color(clrChannelEpgTimeFg), 0x88000000, cFont::GetFont(fontSml), osd->Width() - lineHeight - 20 - timeWidth);
      }
   }
   if (duration > -1) {
      osd->DrawRectangle(timeWidth + 4, OffsetArea2               , timeWidth + 11, OffsetArea2 + 4 * lineHeight    , 0xBBAA1111);
//      osd->DrawRectangle(timeWidth + 5, OffsetArea2 + 1           , timeWidth +  9, OffsetArea2 + 4 * lineHeight - 2, Theme4col.Color(clrChannelEpgTimeFg));
      osd->DrawRectangle(timeWidth + 5, OffsetArea2 + 1 + duration, timeWidth + 9 , OffsetArea2 + 4 * lineHeight - 2, 0x88000000);
   }
}

void cSkinSvenHelauDisplayChannel::SetMessage(eMessageType Type, const char *Text)
{
   const cFont *font = cFont::GetFont(fontOsd);
   if (Text) {
      osd->SaveRegion(0, 0, osd->Width() - 1, lineHeight - 1);
      osd->DrawRectangle(font->Height()                       , 0, Setup.OSDWidth - font->Height(), font->Height(), 0xCC2233CC);
      osd->DrawEllipse  (0                                    , 0, font->Height() / 2             , font->Height(), 0xCC2233CC, 7);
      osd->DrawEllipse  (Setup.OSDWidth - (font->Height() / 2), 0, Setup.OSDWidth - 1             , font->Height(), 0xCC2233CC, 5);
      osd->DrawText(font->Height() / 2, 0, Text, 0xFFFFFFFF, 0xCC2233CC, font, Setup.OSDWidth - font->Height() + 1, 0, taCenter);
      message = true;
   }
   else {
      osd->RestoreRegion();
      message = false;
   }
}

void cSkinSvenHelauDisplayChannel::Flush(void)
{
   if (!message) {
      cString date = DayDateTime();
      osd->DrawRectangle(osd->Width() / 3 * 2                        , int(1.5 * lineHeight), osd->Width() / 3 * 2 + int(1.8 * lineHeight), 2 * lineHeight - 1, 0x77000066);
      osd->DrawEllipse  (osd->Width() / 3 * 2 + int(lineHeight * .8) , lineHeight           , osd->Width() / 3 * 2 + int(1.8 * lineHeight), 2 * lineHeight    , 0x77000066, 2);
      osd->DrawRectangle(osd->Width() / 3 * 2 + int(1.5 * lineHeight), lineHeight           , osd->Width() - lineHeight                   , 2 * lineHeight - 1, 0x77000066);
      osd->DrawEllipse  (osd->Width() / 3 * 2                        , lineHeight           , osd->Width() / 3 * 2 + lineHeight           , 2 * lineHeight - 1, 0x00FFFFFF, 4);
      osd->DrawText(osd->Width() - cFont::GetFont(fontSml)->Width(date) - lineHeight, lineHeight, date, 0xFFFFFFFF, 0x77000066, cFont::GetFont(fontSml));
   }
   osd->Flush();
}

// --- cSkinClassicDisplayMenu -----------------------------------------------

class cSkinSvenHelauDisplayMenu : public cSkinDisplayMenu {
private:
   cOsd *osd;
   int x0, x1;
   int y0, y1, y2, y3, y4, y5;
   int lineHeight;
   void SetScrollbar(void);
public:
   cSkinSvenHelauDisplayMenu(void);
   virtual ~cSkinSvenHelauDisplayMenu();
   virtual void Scroll(bool Up, bool Page);
   virtual int MaxItems(void);
   virtual void Clear(void);
   virtual void SetTitle(const char *Title);
   virtual void SetButtons(const char *Red, const char *Green = NULL, const char *Yellow = NULL, const char *Blue = NULL);
   virtual void SetMessage(eMessageType Type, const char *Text);
   virtual void SetItem(const char *Text, int Index, bool Current, bool Selectable);
   virtual void SetEvent(const cEvent *Event);
   virtual void SetRecording(const cRecording *Recording);
   virtual void SetText(const char *Text, bool FixedFont);
   virtual void Flush(void);
};

cSkinSvenHelauDisplayMenu::cSkinSvenHelauDisplayMenu(void)
{
   const cFont *font = cFont::GetFont(fontOsd);
   lineHeight = font->Height();
   x0 = 0;
   x1 = Setup.OSDWidth;
   y0 = 0;
   y1 = lineHeight;
   y2 = y1 + lineHeight;
   y5 = Setup.OSDHeight;
   y4 = y5 - lineHeight;
   y3 = y4 - lineHeight;


   // WIDTH HEIGHT STRATEGY
// if((x1*y5) > (500*320)) {
//    while(((x1*y5) > (500*320)) || ((widthsizer > 0) && (x1%4 != 0))) {
//       y5 -= heightsizer;
//       x1 -= widthsizer;
//    }
//
//    y4 = y5 - lineHeight;
//    y3 = y4 - lineHeight;
//
//    xdif = (Setup.OSDWidth - x1)/2;
//    ydif = (Setup.OSDHeight - y5)/2;
// }

   osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop);
//   tArea Areas[] = { { x0, y0, x1 - 1, y5 - 1, 2},
//      { x0, y5, x1 -((x1-x0)/4) -1, y5 + (y5-y4)-1, 2},
//      { x0, y4, x1 -((x1-x0)/4) -1, y5 -1, 2}
//   };
   tArea Areas[] = { { x0, y0, x1 - 1, y5 - 1, 2} };   

   Dprintf("1st area at %d %d %d %d(x1,y1,x2,y2)\n",x0, y0, x1 - 1, y5 - 1);

   /*if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
   else {
      tArea Areas[] = { { x0, y0, x1 - 1, y1 - 1, 2 },
                        { x0, y1, x1 - 1, y3 - 1, 2 },
                        { x0, y3, x1 - 1, y5 - 1, 4 }
                      };
      osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
      }*/
   osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
   osd->DrawRectangle(x0, y0, x1 - 1, y5 - 1, 0x00FFFFFF);
}

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

void cSkinSvenHelauDisplayMenu::SetScrollbar(void)
{
/*
  if (textScroller.CanScroll()) {
     int yt = textScroller.Top();
     int yb = yt + textScroller.Height();
     int st = yt;
     int sb = yb;
     int tt = st + (sb - st) * textScroller.Offset() / textScroller.Total();
     int tb = tt + (sb - st) * textScroller.Shown() / textScroller.Total();
     int xl = x1 - ScrollWidth;
     osd->DrawRectangle(xl, st, x1 - 1, sb, Theme4col.Color(clrMenuScrollbarTotal));
     osd->DrawRectangle(xl, tt, x1 - 1, tb, Theme4col.Color(clrMenuScrollbarShown));
     }
*/
}

void cSkinSvenHelauDisplayMenu::Scroll(bool Up, bool Page)
{
   cSkinDisplayMenu::Scroll(Up, Page);
   SetScrollbar();
}

int cSkinSvenHelauDisplayMenu::MaxItems(void)
{
   return(y3 - y2) / lineHeight;
}

void cSkinSvenHelauDisplayMenu::Clear(void)
{
   textScroller.Reset();
   osd->DrawRectangle(x0, cFont::GetFont(fontSml)->Height(), x1 - 1, y5 - 1, 0x77000066);
   osd->DrawRectangle(osd->Width() - lineHeight, cFont::GetFont(fontSml)->Height(), osd->Width() - 1, 2 * cFont::GetFont(fontSml)->Height(), 0x00FFFFFF);
   osd->DrawEllipse  (osd->Width() - lineHeight, cFont::GetFont(fontSml)->Height(), osd->Width() - 1, 2 * cFont::GetFont(fontSml)->Height(), 0x77000066, 1);
}

void cSkinSvenHelauDisplayMenu::SetTitle(const char *Title)
{
   const cFont *font = cFont::GetFont(fontSml);
   osd->DrawEllipse  (0                                                           , 0                        , font->Height()                                               , font->Height() - 1, 0xCC2233CC, 2);
   osd->DrawRectangle(font->Height()                                              , 0                        , osd->Width() / 3 * 2 - lineHeight                            , font->Height() - 1, 0xCC2233CC);
   osd->DrawRectangle(osd->Width() / 3 * 2 - lineHeight                           , int(0.5 * font->Height()), osd->Width() / 3 * 2 - lineHeight + int(1.8 * font->Height()), font->Height() - 1, 0xCC2233CC);
   osd->DrawEllipse  (osd->Width() / 3 * 2 - lineHeight                           , 0 * font->Height()       , osd->Width() / 3 * 2 - lineHeight + font->Height()           , font->Height() - 1, 0xCC2233CC, 1);
   osd->DrawEllipse  (osd->Width() / 3 * 2 - lineHeight + int(font->Height() * .8), 0 * font->Height()       , osd->Width() / 3 * 2 - lineHeight + int(1.8 * font->Height()), font->Height() - 1, 0x00FFFFFF, 3);
   osd->DrawText(font->Height(), 0, Title, 0xFFFFFFFF, 0xCC2233CC, font);
}

void cSkinSvenHelauDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
{
   const cFont *font = cFont::GetFont(fontOsd);
   int w = x1 - x0;
   int t0 = x0;
   int t1 = x0 + w / 4;
   int t2 = x0 + w / 2;
   int t3 = x1 - w / 4;
   int t4 = x1;

   if (Red)
      osd->DrawText(t0, y5, Red   , 0xFFFFFFFF, 0xBBAA1111, font, t1 - t0, 0, taCenter);
   if (Green)
      osd->DrawText(t1, y5, Green , 0xFFFFFFFF, 0xBB11AA11, font, t2 - t1, 0, taCenter);
   if (Yellow)
      osd->DrawText(t2, y5, Yellow, 0xFFFFFFFF, 0xBBAAAA11, font, t3 - t2, 0, taCenter);
   if (Blue)
      osd->DrawText(t3, y4-1, Blue, 0xFFFFFFFF, 0xCC2233CC, font, t4 - t3, 0, taCenter);
}

void cSkinSvenHelauDisplayMenu::SetMessage(eMessageType Type, const char *Text)
{
   const cFont *font = cFont::GetFont(fontOsd);
   if (Text)
      osd->DrawText(x0, y3, Text, 0xFFFFFFFF, 0xCC2233CC, font, x1 - x0, 0, taCenter);
   //osd->DrawText(x0, y3, Text, Theme4col.Color(clrMessageStatusFg + 2 * Type), Theme4col.Color(clrMessageStatusBg + 2 * Type), font, x1 - x0, 0, taCenter);
   else
      osd->DrawRectangle(x0, y3, x1 - 1, y4 - 1, 0x77000066);
}

void cSkinSvenHelauDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable)
{
   int y = y2 + Index * lineHeight;
   tColor ColorFg, ColorBg;
   if (Current) {
      ColorFg = 0xFFFFFFFF;
      ColorBg = 0xCC2233CC;
   }
   else {
      ColorFg = Selectable ? 0xFFFFFFFF : 0x77000066;
      ColorBg = 0x77000066;
   }
   const cFont *font = cFont::GetFont(fontOsd);
   for (int i = 0; i < MaxTabs; i++) {
      const char *s = GetTabbedText(Text, i);
      if (s) {
         int xt = x0 + Tab(i);
         osd->DrawText   (xt + (font->Height() /2 ), y, s, ColorFg, ColorBg, font, x1 - xt - font->Height() + 1);
         if (Current) {
            osd->DrawEllipse(xt, y, xt + (font->Height() / 2 ), y + font->Height() - 1, 0xCC2233CC, 7);
            osd->DrawEllipse(x1 - (font->Height() / 2 ), y, x1 - 1, y + font->Height() - 1, 0xCC2233CC, 5);
         }
         else {
            osd->DrawRectangle(xt, y, xt + (font->Height() / 2 ), y + font->Height() - 1, 0x77000066);
            osd->DrawRectangle(x1 - (font->Height() / 2 ), y, x1, y + font->Height() - 1, 0x77000066);
         }
      }
      if (!Tab(i + 1))
         break;
   }
   SetEditableWidth(x1 - x0 - Tab(1));
}

void cSkinSvenHelauDisplayMenu::SetEvent(const cEvent *Event)
{
   if (!Event)
      return;
   const cFont *font = cFont::GetFont(fontOsd);
   int xl = x0 + 10;
   int y = y2;
   cTextScroller ts;
   char t[32];
   snprintf(t, sizeof(t), "%s  %s - %s", *Event->GetDateString(), *Event->GetTimeString(), *Event->GetEndTimeString());
   ts.Set(osd, xl, y, x1 - xl, y3 - y, t, font, 0xFFFFFFFF, 0x77000066);
   if (Event->Vps() && Event->Vps() != Event->StartTime()) {
      char *buffer;
      asprintf(&buffer, " VPS: %s", *Event->GetVpsString());
      const cFont *font = cFont::GetFont(fontSml);
      osd->DrawText(x1 - font->Width(buffer), y, buffer, 0xFFFFFFFF, 0x77000066, font);
      free(buffer);
   }
   y += ts.Height();
   y += font->Height();
   ts.Set(osd, xl, y, x1 - xl, y3 - y, Event->Title(), font, 0xFFFFFFFF, 0x77000066);
   y += ts.Height();
   if (!isempty(Event->ShortText())) {
      const cFont *font = cFont::GetFont(fontSml);
      ts.Set(osd, xl, y, x1 - xl, y3 - y, Event->ShortText(), font, 0xFFFFFFFF, 0x77000066);
      y += ts.Height();
   }
   y += font->Height();
   if (!isempty(Event->Description())) {
      textScroller.Set(osd, xl, y, x1 - xl - 2 * ScrollWidth, y3 - y, Event->Description(), font, 0xFFFFFFFF, 0x77000066);
      SetScrollbar();
   }
}

void cSkinSvenHelauDisplayMenu::SetRecording(const cRecording *Recording)
{
/*
  // added new recodringinfo-support from VDR >= 1.3.25
#if VDRVERSNUM <= 10324
  SetText(Recording->Summary(), false); //TODO
#else
*/
   if (!Recording)
      return;
   const cRecordingInfo *Info = Recording->Info();
   const cFont *font = cFont::GetFont(fontOsd);
   int xl = x0 + 10;
   int y = y2;
   cTextScroller ts;
   char t[32];
   snprintf(t, sizeof(t), "%s  %s", *DateString(Recording->start), *TimeString(Recording->start));
   ts.Set(osd, xl, y, x1 - xl, y3 - y, t, font, 0xFFFFFFFF, 0x77000066);
   y += ts.Height();
   y += font->Height();
   const char *Title = Info->Title();
   if (isempty(Title))
      Title = Recording->Name();
   ts.Set(osd, xl, y, x1 - xl, y3 - y, Title, font, 0xFFFFFFFF, 0x77000066);
   y += ts.Height();
   if (!isempty(Info->ShortText())) {
      const cFont *font = cFont::GetFont(fontSml);
      ts.Set(osd, xl, y, x1 - xl, y3 - y, Info->ShortText(), font, 0xFFFFFFFF, 0x77000066);
      y += ts.Height();
   }
   y += font->Height();
   if (!isempty(Info->Description())) {
      textScroller.Set(osd, xl, y, x1 - xl - 2 * ScrollWidth, y3 - y, Info->Description(), font, 0xFFFFFFFF, 0x77000066);
      SetScrollbar();
   }
/*#endif*/
}

void cSkinSvenHelauDisplayMenu::SetText(const char *Text, bool FixedFont)
{
   const cFont *font = cFont::GetFont(fontOsd);//FixedFont ? fontFix : fontOsd);
   textScroller.Set(osd, x0, y2, x1 - x0 - 2 * ScrollWidth, y3 - y2, Text, font, 0xFFFFFFFF, 0x77000066);
   SetScrollbar();
}


void cSkinSvenHelauDisplayMenu::Flush(void)
{
   cString date = DayDateTime();
   const cFont *font = cFont::GetFont(fontSml);
   osd->DrawText(x1 - font->Width(date) - lineHeight, 0, date, 0xFFFFFFFF, 0x00FFFFFF, font);
   osd->Flush();
}

// --- cSkinClassicDisplayReplay ---------------------------------------------

class cSkinSvenHelauDisplayReplay : public cSkinDisplayReplay {
private:
   cOsd *osd;
   int x0, x1;
   int y0, y1, y2, y3;
   int lastCurrentWidth;
   bool message;
   static cBitmap bmTemp, bmFrew, bmSrew, bmPause, bmPlay, bmSfwd, bmFfwd, bmFfwd1, bmFfwd2, bmFfwd3, bmFrew1, bmFrew2, bmFrew3, bmSrew1, bmSrew2, bmSrew3, bmSfwd1, bmSfwd2, bmSfwd3;
   bool blnModeOnly;
public:
   cSkinSvenHelauDisplayReplay(bool ModeOnly);
   virtual ~cSkinSvenHelauDisplayReplay();
   virtual void SetTitle(const char *Title);
   virtual void SetMode(bool Play, bool Forward, int Speed);
   virtual void SetProgress(int Current, int Total);
   virtual void SetCurrent(const char *Current);
   virtual void SetTotal(const char *Total);
   virtual void SetJump(const char *Jump);
   virtual void SetMessage(eMessageType Type, const char *Text);
   virtual void Flush(void);
};

cBitmap cSkinSvenHelauDisplayReplay::bmTemp(frew_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmFrew(frew_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmFrew1(frew1_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmFrew2(frew2_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmFrew3(frew3_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmSrew(srew_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmSrew1(srew1_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmSrew2(srew2_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmSrew3(srew3_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmPause(pause_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmPlay(play_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmSfwd(sfwd_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmSfwd1(sfwd1_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmSfwd2(sfwd2_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmSfwd3(sfwd3_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmFfwd(ffwd_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmFfwd1(ffwd1_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmFfwd2(ffwd2_xpm);
cBitmap cSkinSvenHelauDisplayReplay::bmFfwd3(ffwd3_xpm);

cSkinSvenHelauDisplayReplay::cSkinSvenHelauDisplayReplay(bool ModeOnly)
{
   blnModeOnly = ModeOnly;
   const cFont *font = cFont::GetFont(fontOsd);
   int lineHeight = font->Height();
   lastCurrentWidth = 0;
   message = false;
   x0 = 0;
   x1 = Setup.OSDWidth;
   y0 = 0;
   y1 = lineHeight;
   y2 = 2 * lineHeight;
   y3 = 4 * lineHeight;
   osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - 5 * lineHeight / 2);
   tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 2}};
   osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
   osd->DrawRectangle(x0, y0, x1 - 1, y3 - 1, 0x00FFFFFF);
}

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

void cSkinSvenHelauDisplayReplay::SetTitle(const char *Title)
{
   const char *Prompt = Title;
   const cFont *font = cFont::GetFont(fontOsd);
   int lineHeight = font->Height();

   osd->DrawRectangle(0                                                             , lineHeight           , osd->Width() - font->Height()                               , 2 * lineHeight    , 0x77000066);
   osd->DrawRectangle(lineHeight                                                    , 2 *lineHeight        , osd->Width() - font->Height()                               , 3 * lineHeight - 1, 0x77000066);
   osd->DrawRectangle(1 * lineHeight + font->Width(Prompt)                          , int(0.5 * lineHeight), 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 1 * lineHeight    , 0x77000066);

   osd->DrawEllipse  (1 * lineHeight + font->Width(Prompt)                          , 0                    , 1 * lineHeight + font->Width(Prompt) + lineHeight           , 1 * lineHeight    , 0x77000066, 1);
   osd->DrawEllipse  (1 * lineHeight + font->Width(Prompt) + int(lineHeight * .8)   , 0                    , 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 1 * lineHeight    , 0x00FFFFFF, 3);
   osd->DrawEllipse  (0                                                             , 0                    , lineHeight                                                  , 1 * lineHeight    , 0x77000066, 2);

   osd->DrawRectangle(lineHeight                                                    , lineHeight           , 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 2 * lineHeight    , 0x77000066);
   osd->DrawText(lineHeight, 0, Prompt, 0xFFFFFFFF, 0x77000066, font);

   osd->DrawRectangle(font->Height()                       , font->Height(), Setup.OSDWidth - font->Height(), 2 * font->Height(), 0x77000066);
   osd->DrawEllipse  (0                                    , 2 * font->Height(), font->Height()             , 3 * font->Height(), 0x77000066, 3);
   osd->DrawEllipse  (Setup.OSDWidth - font->Height()      , font->Height(), Setup.OSDWidth - 1             , 3 * font->Height(), 0x77000066, 5);
}

void cSkinSvenHelauDisplayReplay::SetMode(bool Play, bool Forward, int Speed)
{
   if (Setup.ShowReplayMode) {
      const cFont *font = cFont::GetFont(fontOsd);
      int lineHeight = font->Height();
      int intX = blnModeOnly ? int(-1.7 * lineHeight) : 2 * lineHeight;
      osd->DrawRectangle(intX + lineHeight                            , 3 * lineHeight, intX + osd->Width() - font->Height() / 2           , 4 * lineHeight - 1, 0x00FFFFFF);
      osd->DrawRectangle(intX + int(2.3 * lineHeight)                 , 2 * lineHeight, intX + int(8.5 + 3.3) * lineHeight                 , 3 * lineHeight - 1, 0x77000066);
      osd->DrawEllipse  (intX + int(2.3 * lineHeight) - lineHeight / 2, 2 * lineHeight, intX + int(2.3 * lineHeight)                       , 3 * lineHeight    , 0x77000066, 7);
      osd->DrawEllipse  (intX + int(8.5 + 3.3) * lineHeight           , 2 * lineHeight, intX + int(8.5 + 3.3) * lineHeight + lineHeight / 2, 3 * lineHeight    , 0x77000066, 5);

      int offsetX = 0;
      int offsetY = int(lineHeight / 4);
      bool blnFrew, blnSrew, blnPause, blnPlay, blnSfwd, blnFfwd;
      blnFrew = false; blnSrew = false; blnPause = false; blnPlay = blnSrew; blnSfwd = false, blnFfwd = false;
      if (Speed == -1 && Play) {
         blnPlay  = true; offsetX = int(5.5 * lineHeight);
      }
      else if (Speed == -1 && !Play) {
         blnPause = true; offsetX = int(4   * lineHeight);
      }
      else if (Play && Forward) {
         blnFfwd  = true; offsetX = int(8.5 * lineHeight);
      }
      else if (Play && !Forward) {
         blnFrew  = true; offsetX = int(1   * lineHeight);
      }
      else if (Forward) {
         blnSfwd  = true; offsetX = int(7   * lineHeight);
      }
      else if (!Forward) {
         blnSrew  = true; offsetX = int(2.5 * lineHeight);
      }

      if (blnFrew && blnModeOnly) {
         osd->DrawEllipse  (intX + int(1.3 * lineHeight + lineHeight / 2), 2 * lineHeight, intX + int(2.3 * lineHeight), int(3.5 * lineHeight), 0x77000066, 7);
         osd->DrawRectangle(intX + int(2.3 * lineHeight)                 , 3 * lineHeight, intX + int(3   * lineHeight), int(3.5 * lineHeight), 0x77000066);
      }
      else {
         osd->DrawRectangle(intX + offsetX + 0                     , 3 * lineHeight, intX + offsetX + int(1.8 * lineHeight), 3 * lineHeight + lineHeight / 4, 0x77000066);
         osd->DrawEllipse  (intX + offsetX + int(0.8 * lineHeight) , 3 * lineHeight, intX + offsetX + int(1.8 * lineHeight), 4 * lineHeight - lineHeight / 2, 0x77000066, 3);
         osd->DrawEllipse  (intX + offsetX + 0                     , 3 * lineHeight, intX + offsetX + lineHeight           , 4 * lineHeight - lineHeight / 2, 0x00FFFFFF, 1);
      }

      osd->DrawRectangle(intX + offsetX + int(1.8 * lineHeight) , 3 * lineHeight, intX + offsetX + 2 * lineHeight       , 4 * lineHeight - lineHeight / 2, 0x77000066);

      if (blnFfwd && blnModeOnly) {
         osd->DrawEllipse  (intX + offsetX + 2 * lineHeight        , 2 * lineHeight, intX + offsetX + 3   * lineHeight     , int(3.5 * lineHeight), 0x77000066, 5);
      }
      else {
         osd->DrawRectangle(intX + offsetX + 2 * lineHeight        , 3 * lineHeight, intX + offsetX + int(3.8 * lineHeight), 3 * lineHeight + lineHeight / 4, 0x77000066);
         osd->DrawEllipse  (intX + offsetX + 2 * lineHeight        , 3 * lineHeight, intX + offsetX + 3 * lineHeight       , 4 * lineHeight - lineHeight / 2, 0x77000066, 4);
         osd->DrawEllipse  (intX + offsetX + int(2.8 * lineHeight) , 3 * lineHeight, intX + offsetX + int(3.8 * lineHeight), 4 * lineHeight - lineHeight / 2, 0x00FFFFFF, 2);
      }
      bmTemp = frew_xpm;
      if (blnFrew && Speed == 1)      bmTemp = frew1_xpm;
      else if (blnFrew && Speed == 2) bmTemp = frew2_xpm;
      else if (blnFrew && Speed == 3) bmTemp = frew3_xpm;
      osd->DrawBitmap(intX + int(2.3 * lineHeight), blnFrew  ? offsetY + 2 * lineHeight : 2 * lineHeight, bmTemp , blnFrew   ? 0xFFFFFFFF :0xCC2233CC, 0x77000066);

      bmTemp = srew_xpm;
      if (blnSrew && Speed == 1)      bmTemp = srew1_xpm;
      else if (blnSrew && Speed == 2) bmTemp = srew2_xpm;
      else if (blnSrew && Speed == 3) bmTemp = srew3_xpm;
      osd->DrawBitmap(intX + int(3.8 * lineHeight), blnSrew  ? offsetY + 2 * lineHeight : 2 * lineHeight, bmTemp , blnSrew   ? 0xFFFFFFFF :0xCC2233CC, 0x77000066);

      osd->DrawBitmap(intX + int(5.3 * lineHeight), blnPause ? offsetY + 2 * lineHeight : 2 * lineHeight, pause_xpm, blnPause  ? 0xFFFFFFFF :0xCC2233CC, 0x77000066);
      osd->DrawBitmap(intX + int(6.8 * lineHeight), blnPlay  ? offsetY + 2 * lineHeight : 2 * lineHeight, play_xpm , blnPlay   ? 0xFFFFFFFF :0xCC2233CC, 0x77000066);

      bmTemp = sfwd_xpm;
      if (blnSfwd && Speed == 1)      bmTemp = sfwd1_xpm;
      else if (blnSfwd && Speed == 2) bmTemp = sfwd2_xpm;
      else if (blnSfwd && Speed == 3)bmTemp = sfwd3_xpm;
      osd->DrawBitmap(intX + int(8.3 * lineHeight), blnSfwd  ? offsetY + 2 * lineHeight : 2 * lineHeight, bmTemp , blnSfwd   ? 0xFFFFFFFF :0xCC2233CC, 0x77000066);

      bmTemp = ffwd_xpm;
      if (blnFfwd && Speed == 1)      bmTemp = ffwd1_xpm;
      else if (blnFfwd && Speed == 2) bmTemp = ffwd2_xpm;
      else if (blnFfwd && Speed == 3) bmTemp = ffwd3_xpm;
      osd->DrawBitmap(intX + int(9.8 * lineHeight), blnFfwd  ? offsetY + 2 * lineHeight : 2 * lineHeight, bmTemp , blnFfwd   ? 0xFFFFFFFF :0xCC2233CC, 0x77000066);
   }
}

void cSkinSvenHelauDisplayReplay::SetProgress(int Current, int Total)
{
   const cFont *font = cFont::GetFont(fontOsd);
   int lineHeight = font->Height();
   cProgressBar pb(osd->Width() - 2 * lineHeight, lineHeight - 6, Current, Total, marks, 0xFFFFFFFF, 0x77000066, 0xCC2233CC, 0xFFFFFFFF, 0xFFFFFFFF);
   osd->DrawBitmap(lineHeight, lineHeight + 6, pb);
}

void cSkinSvenHelauDisplayReplay::SetCurrent(const char *Current)
{
   const cFont *font = cFont::GetFont(fontOsd);
   int lineHeight = font->Height();
   int w = font->Width(Current);
   osd->DrawText(lineHeight, 2 * lineHeight, Current, 0xFFFFFFFF, 0x77000066, font, lastCurrentWidth > w ? lastCurrentWidth : 0);
   lastCurrentWidth = w;
}

void cSkinSvenHelauDisplayReplay::SetTotal(const char *Total)
{
   const cFont *font = cFont::GetFont(fontOsd);
   int lineHeight = font->Height();
   osd->DrawText(x1 - font->Width(Total) - lineHeight, 2 * lineHeight, Total, 0xFFFFFFFF, 0x77000066, font);
}

void cSkinSvenHelauDisplayReplay::SetJump(const char *Jump)
{
//  osd->DrawText(x0 + (x1 - x0) / 4, y2, Jump, Theme4col.Color(clrReplayModeJump), Theme4col.Color(clrReplayBackgroundNew), cFont::GetFont(fontOsd), (x1 - x0) / 2, 0, taCenter);
}

void cSkinSvenHelauDisplayReplay::SetMessage(eMessageType Type, const char *Text)
{

   const cFont *font = cFont::GetFont(fontOsd);
   int lineHeight = font->Height();
   if (Text) {
      osd->SaveRegion(0, 0, osd->Width() - 1, lineHeight - 1);
      osd->DrawRectangle(font->Height()                       , 3 * lineHeight, Setup.OSDWidth - font->Height(), 4 * lineHeight, 0xCC2233CC);
      osd->DrawEllipse  (0                                    , 3 * lineHeight, font->Height() / 2             , 4 * lineHeight, 0xCC2233CC, 7);
      osd->DrawEllipse  (Setup.OSDWidth - (font->Height() / 2), 3 * lineHeight, Setup.OSDWidth - 1             , 4 * lineHeight, 0xCC2233CC, 5);
      osd->DrawText(font->Height() / 2, 3 * lineHeight, Text, 0xFFFFFFFF, 0xCC2233CC, font, Setup.OSDWidth - font->Height() + 1, 0, taCenter);
      message = true;
   }
   else {
      osd->RestoreRegion();
      message = false;
   }
}

void cSkinSvenHelauDisplayReplay::Flush(void)
{
   osd->Flush();
}

// --- cSkinClassicDisplayVolume ---------------------------------------------

class cSkinSvenHelauDisplayVolume : public cSkinDisplayVolume {
private:
   cOsd *osd;
public:
   cSkinSvenHelauDisplayVolume(void);
   virtual ~cSkinSvenHelauDisplayVolume();
   virtual void SetVolume(int Current, int Total, bool Mute);
   virtual void Flush(void);
};

cSkinSvenHelauDisplayVolume::cSkinSvenHelauDisplayVolume(void)
{
   const cFont *font = cFont::GetFont(fontOsd);
   int lineHeight = font->Height();
   osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - lineHeight);
   tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, 2 * lineHeight - 1, 2}};
   osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}

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

void cSkinSvenHelauDisplayVolume::SetVolume(int Current, int Total, bool Mute)
{
   const cFont *font = cFont::GetFont(fontOsd);
   osd->DrawRectangle(0, 0, osd->Width() , osd->Height(), 0x00FFFFFF);
   if (Mute) {
      osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, 0x00FFFFFF);
      osd->DrawRectangle(font->Height(), 0, font->Height() + 10 + font->Width("Mute"), font->Height(), 0x77000066);
      osd->DrawEllipse  (0, 0, font->Height() / 2, font->Height(), 0x77000066, 7);
      osd->DrawText(font->Height() / 2, 0, tr("Mute"), 0xFFFFFFFF, 0x77000066, font);
      osd->DrawEllipse (font->Height() + 10 + font->Width("Mute"), 0, font->Height() * 3 / 2 + 10 + font->Width("Mute"), font->Height(), 0x77000066, 5);
   }
   else {
      const char *Prompt = tr("Volume ");
      int lineHeight = font->Height();
      int l = lineHeight;
      int p = (osd->Width() - lineHeight / 2 - l) * Current / Total;
      osd->DrawRectangle(l                                                             , lineHeight           , osd->Width() - font->Height() / 2                           , 2 *lineHeight - 1, 0x77000066);
      osd->DrawRectangle(1 * lineHeight + font->Width(Prompt)                          , int(0.5 * lineHeight), 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 1 * lineHeight   , 0x77000066);
      osd->DrawEllipse (osd->Width() - lineHeight / 2                                  , lineHeight           , osd->Width() - 1                                            , 2 * lineHeight   , 0x77000066, 5);
      osd->DrawEllipse  (1 * lineHeight + font->Width(Prompt)                          , 0                    , 1 * lineHeight + font->Width(Prompt) + lineHeight           , 1 * lineHeight   , 0x77000066, 1);
      osd->DrawEllipse  (1 * lineHeight + font->Width(Prompt) + int(lineHeight * .8)   , 0                    , 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 1 * lineHeight   , 0x00FFFFFF, 3);
      osd->DrawEllipse  (0                                                             , 0                    , lineHeight                                                  , 2 * lineHeight   , 0x77000066, 7);
      osd->DrawRectangle(lineHeight                                                    , lineHeight           , 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 2 * lineHeight   , 0x77000066);
      osd->DrawText(lineHeight, 0, Prompt, 0xFFFFFFFF, 0x77000066, font);
      osd->DrawRectangle(l, lineHeight + lineHeight / 4, osd->Width() - lineHeight / 2, 2 * lineHeight - 1 - lineHeight / 4, 0x00FFFFFF);
      int step = 8;
      for (int i=0; i<=p; i+= step) {
         osd->DrawRectangle(l + i, lineHeight + lineHeight / 4, l + i + step - 3 , 2 * lineHeight - 1 - lineHeight / 4, 0xCC2233CC);
      }
      char *temp;
      temp = (char *) malloc(24);
      sprintf(temp,"%d",Current);
      osd->DrawText(osd->Width() - font->Width(temp) - (lineHeight / 2), 0, temp, 0xFFFFFFFF, 0x00FFFFFF, font);
   }
}

void cSkinSvenHelauDisplayVolume::Flush(void)
{
   osd->Flush();
}

// --- cSkinClassicDisplayTracks ---------------------------------------------

class cSkinSvenHelauDisplayTracks : public cSkinDisplayTracks {
private:
   cOsd *osd;
   int x0, x1;
   int y0, y1, y2;
   int lineHeight;
   int currentIndex;
   void SetItem(const char *Text, int Index, bool Current);
public:
   cSkinSvenHelauDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks);
   virtual ~cSkinSvenHelauDisplayTracks();
   virtual void SetTrack(int Index, const char * const *Tracks);
   virtual void SetAudioChannel(int AudioChannel) {}
   virtual void Flush(void);
};

cSkinSvenHelauDisplayTracks::cSkinSvenHelauDisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
{
   const cFont *font = cFont::GetFont(fontOsd);
   lineHeight = font->Height();
   currentIndex = -1;
   int ItemsWidth = font->Width(Title);
   for (int i = 0; i < NumTracks; i++)
      ItemsWidth = max(ItemsWidth, font->Width(Tracks[i]));
   ItemsWidth += 10;
   x0 = 0;
   x1 = Setup.OSDWidth;
   int d = x1 - x0;
   if (d > ItemsWidth) {
      d = (d - ItemsWidth) & ~0x07; // must be multiple of 8
      x1 -= d;
   }
   y0 = 0;
   y1 = lineHeight;
   y2 = y1 + NumTracks * lineHeight;
   osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y2);
   tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 2}};
   osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
   osd->DrawText(x0, y0, Title, Theme4col.Color(clrMenuTitleFg), Theme4col.Color(clrMenuTitleBg), font, x1 - x0);
   for (int i = 0; i < NumTracks; i++)
      SetItem(Tracks[i], i, false);
}

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

void cSkinSvenHelauDisplayTracks::SetItem(const char *Text, int Index, bool Current)
{
   int y = y1 + Index * lineHeight;
   tColor ColorFg, ColorBg;
   if (Current) {
      ColorFg = Theme4col.Color(clrMenuItemCurrentFg);
      ColorBg = Theme4col.Color(clrMenuItemCurrentBg);
      currentIndex = Index;
   }
   else {
      ColorFg = Theme4col.Color(clrMenuItemSelectable);
      ColorBg = Theme4col.Color(clrTracksBackgroundNew);
   }
   const cFont *font = cFont::GetFont(fontOsd);
   osd->DrawText(x0, y, Text, ColorFg, ColorBg, font, x1 - x0);
}

void cSkinSvenHelauDisplayTracks::SetTrack(int Index, const char * const *Tracks)
{
   if (currentIndex >= 0)
      SetItem(Tracks[currentIndex], currentIndex, false);
   SetItem(Tracks[Index], Index, true);
}

void cSkinSvenHelauDisplayTracks::Flush(void)
{
   osd->Flush();
}

// --- cSkinClassicDisplayMessage --------------------------------------------

class cSkinSvenHelauDisplayMessage : public cSkinDisplayMessage {
private:
   cOsd *osd;
public:
   cSkinSvenHelauDisplayMessage(void);
   virtual ~cSkinSvenHelauDisplayMessage();
   virtual void SetMessage(eMessageType Type, const char *Text);
   virtual void Flush(void);
};

cSkinSvenHelauDisplayMessage::cSkinSvenHelauDisplayMessage(void)
{
   const cFont *font = cFont::GetFont(fontOsd);
   int lineHeight = font->Height();
   osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - lineHeight);
   tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, 2 * lineHeight - 1, 2}};
   osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
   osd->DrawRectangle(0, 0, Setup.OSDWidth - 1, 2 * lineHeight - 1, 0x00FFFFFF);
}

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

void cSkinSvenHelauDisplayMessage::SetMessage(eMessageType Type, const char *Text)
{
   const cFont *font = cFont::GetFont(fontOsd);
   const char *Prompt = tr("Info ");
   int lineHeight = font->Height();
   osd->DrawRectangle(lineHeight                                                    , lineHeight           , osd->Width() - font->Height() / 2                           , 2 * lineHeight - 1, 0x77000066);
   osd->DrawRectangle(1 * lineHeight + font->Width(Prompt)                          , int(0.5 * lineHeight), 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 1 * lineHeight   , 0x77000066);
   osd->DrawEllipse  (osd->Width() - lineHeight / 2                                 , lineHeight           , osd->Width() - 1                                            , 2 * lineHeight   , 0x77000066, 5);
   osd->DrawEllipse  (1 * lineHeight + font->Width(Prompt)                          , 0                    , 1 * lineHeight + font->Width(Prompt) + lineHeight           , 1 * lineHeight   , 0x77000066, 1);
   osd->DrawEllipse  (1 * lineHeight + font->Width(Prompt) + int(lineHeight * .8)   , 0                    , 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 1 * lineHeight   , 0x00FFFFFF, 3);
   osd->DrawEllipse  (0                                                             , 0                    , lineHeight                                                  , 2 * lineHeight   , 0x77000066, 7);
   osd->DrawRectangle(lineHeight                                                    , lineHeight           , 1 * lineHeight + font->Width(Prompt) + int(1.8 * lineHeight), 2 * lineHeight   , 0x77000066);
   osd->DrawText(lineHeight, 0, Prompt, 0xCC2233CC, 0x77000066, font);

   osd->DrawRectangle(font->Height()                       , font->Height(), Setup.OSDWidth - font->Height(), 2 * font->Height(), 0x77000066);
   osd->DrawEllipse  (0                                    , font->Height(), font->Height()                 , 2 * font->Height(), 0x77000066, 3);
   osd->DrawEllipse  (Setup.OSDWidth - (font->Height() / 2), font->Height(), Setup.OSDWidth - 1             , 2 * font->Height(), 0x77000066, 5);
   osd->DrawText(font->Height()                            , font->Height(), Text                           , 0xFFFFFFFF        , 0x77000066, font, Setup.OSDWidth - 2 * font->Height() + 1, 0, taCenter);
}

void cSkinSvenHelauDisplayMessage::Flush(void)
{
   osd->Flush();
}

// --- cSkinClassic ----------------------------------------------------------

cSkinSvenHelau::cSkinSvenHelau(void)
:cSkin("svenhelau", &::Theme4col)//XXX naming problem???
{
}

const char *cSkinSvenHelau::Description(void)
{
   return tr("SvenHelau - em84 2mb skin");
}

cSkinDisplayChannel *cSkinSvenHelau::DisplayChannel(bool WithInfo)
{
   return new cSkinSvenHelauDisplayChannel(WithInfo);
}

cSkinDisplayMenu *cSkinSvenHelau::DisplayMenu(void)
{
   return new cSkinSvenHelauDisplayMenu;
}

cSkinDisplayReplay *cSkinSvenHelau::DisplayReplay(bool ModeOnly)
{
   return new cSkinSvenHelauDisplayReplay(ModeOnly);
}

cSkinDisplayVolume *cSkinSvenHelau::DisplayVolume(void)
{
   return new cSkinSvenHelauDisplayVolume;
}


cSkinDisplayTracks *cSkinSvenHelau::DisplayTracks(const char *Title, int NumTracks, const char * const *Tracks)
{
   return new cSkinSvenHelauDisplayTracks(Title, NumTracks, Tracks);
}

cSkinDisplayMessage *cSkinSvenHelau::DisplayMessage(void)
{
   return new cSkinSvenHelauDisplayMessage;
}
