/* SwissBetty-TV-Fernbedienung: appfinder.c */

#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "StdTypes.h"
#include "LPC22xx.h"
#include "setup.h"
#include "serial.h"
#include "tasten.h"
#include "cmd.h"
#include "conv.h"
#include "systemtick.h"
#include "gdi.h"
#include "menu.h"
#include "events.h"

/*
 Dies ist der Starter für BettyBase-Anwendungen (Apps).
 Apps sind hinter BettyBase im Flashrom1 oder im Flashrom 2 angesiedelt und
 beginnen immer an einer glatten 32 K Grenze. Sie haben einen charakteristischen
 Anfang, woran der Appfinder sie erkennt.
 Gefundene Apps werden als Liste angezeigt und können gestartet werden.
 ROM1  80000000h..800FFFFFh
 ROM2  82000000h..810FFFFFh
 */


#define PAPP struct TAppHeader

struct TAppHeader
{ dword  Signatur1;                     /* "BETTYAPP"                         */
  dword  Signatur2;
  dword  Flags;                         /* diverse Flags, z.Z. unbelegt       */
  PAPP*  Alloc;                         /* ab welcher Speicheradresse gelinkt */
  long  (*Start) (void);                /* wo der Code beginnt                */
  dword  Icon;                          /* ein Icon zur evtl. Anzeige         */
  char*  Name;                          /* Wie die App heißt                  */
  char*  Descr;                         /* ggf. eine Erläuterung              */
};

#define appmaxnum 32

PAPP* Appliste[appmaxnum];
int   AppAnzahl;
int   ListenOffset;
int   FocussedApp;


#define AppSignatur1  0x54544542
#define AppSignatur2  0x50504159

void ScanRomForApps (void)
{ int    i;
  PAPP*  P;

  i = 0;
  P = (PAPP*) 0x80010000;           /* die ersten 64 K erstmal für BettyBase */

  while (((dword)P < 0x820FFFFF) && (i < appmaxnum))
  { Appliste[i] = 0;
    if ((P->Signatur1 == AppSignatur1) &&
        (P->Signatur2 == AppSignatur2))
    { V24_StrOut("App @ ");
      HexL_Out((dword)P);
      V24_StrOut(": ");
      V24_StrOut(P->Name);
      if (P == P->Alloc)
      { Appliste[i] = P;
        ++i;
	V24_StrOut(" ..ok");
      }
      else V24_StrOut(" ..Alloc falsch");
      V24_CRLF();
    }
    P = (PAPP*) ((dword)P + 0x8000);       /* die nächsten 32 K */
    if (((dword)P > 0x800FFFFF) &&
        ((dword)P < 0x82000000)) P = (PAPP*) 0x82000000;
  }
  AppAnzahl = i;
}



/* Appfinder initialisieren */
void Appfinder_Liste_OnEvent (RCST *self, word *aEvent)
{ if (*aEvent == idMenuInit)
  { ListenOffset = AppAnzahl = 0;
    FocussedApp = -1;
    ScanRomForApps();
    if (AppAnzahl > 0) FocussedApp = 0;   /* die erste eben.. */
  }
}

/* Auswahl-Liste auf Bildschirm zeichnen */
void Appfinder_Liste_Draw (RCST* self)
{ RECT  R;
  RECT  RR;
  int i;

  R = self->R;
  LocalToScreen(self,&R);
  CgFillRect (&R, white);
  if (self->Flags & debrect) Umrande(&R, black);

  if (AppAnzahl==0)
  { CgStr_at (R.left+10, R.top+10, "keine Apps gefunden", black | idf_Helv_12B);
    return;
  }

  RR.left = R.left + 2;
  RR.right = R.right - 2;
  RR.top = R.top + 2;
  RR.bottom = RR.top + 20;

  i = ListenOffset;
  while ((i < AppAnzahl) && (RR.bottom < R.bottom - 1))
  { if (Ich_selected(self) && (FocussedApp == i))  CgFillRect (&RR, ltgr);
    CgStr_at (RR.left+2, RR.top+1, Appliste[i]->Name, black | idf_Helv_14B);
    ++i;
    RR.top = RR.bottom + 2;
    RR.bottom = RR.top + 20;
  }
}


void Appfinder_Liste_OnKey (RCST *self, word *aKey)
{ long retval;
  char* P;
  char S[100];
  char H[12];


  if (*aKey == idEscapeTaste)
  { Add_Event(idMenuSelect1);
    *aKey = 0;
    return;
  }

  if (*aKey == idRaufTaste)
  { if (FocussedApp == 0) return;            /* rauf bei oberster Zeile --> zum Escapefeld */
    --FocussedApp;
    --ListenOffset;
    if (ListenOffset < 0) ListenOffset = 0;
    self->Draw(self);
    *aKey = 0;
    return;
  }

  if (*aKey == idRunterTaste)
  { ++FocussedApp;
    if (FocussedApp >= AppAnzahl) FocussedApp = AppAnzahl - 1;
    if (ListenOffset < (FocussedApp-5)) ListenOffset = FocussedApp-5;
    self->Draw(self);
    *aKey = 0;
    return;
  }

  if (*aKey == idEnterTaste)
  {  if (AppAnzahl==0) return;
     retval = Appliste[FocussedApp]->Start();
     *aKey = 0;
     if (retval)
     { P = Appliste[FocussedApp]->Name;
       StringCopy(S, P, sizeof(S));
       StringAdd(S, " endet mit ", sizeof(S));
       LONGtoStr (retval, 1, H, sizeof(H));
       StringAdd(S, H, sizeof(S));
       Messagebox ("App beendet", S);
       Add_Delayed_Event(2000, idMenuRedraw);
     }
  }
}
