/*
**
**      Projekt         : ShowPicasso - IFF für PicassoII
**      Version         : 1.06
**      File            : ShowPicasso
**      Status          : Public Domain
**
**      Autor           : Michael Ranner
**      Datum           : 7. November 1993
**      Letzte Änderung : 23. Juli 1994
**
**      This programm will only run, if the monitor file supplied
**      with your graphics card is installed and running.
**
**      Anmerkung       : keine
**
*/

#undef TIME  /* Ausgabe der Zeit des Bildaufbaus */

extern struct Library *SysBase;
extern struct Library *DOSBase;
struct Library   *VilIntuiBase;
struct Library  *IntuitionBase;
struct Library       *IconBase;
struct Library  *WorkbenchBase;
struct Library        *AslBase;
struct Library   *ReqToolsBase;
struct Library        *GfxBase;
struct Library   *IFFParseBase;
struct Library     *LocaleBase;

#include "ShowPicasso.h"

struct Catalog *catalog = NULL;


/* Versionsstring und Template */

static UBYTE version[] = "$VER: ShowPicasso 1.06 - © Michael Ranner (23.07.94)";
static UBYTE templ[]   = "Filename/M,DD=DefDir/K,Pat/K,CB=CBuf/K/N,NC=NoCenter/S,NS=NoAutoScroll/S,"
                         "BH=Behind/S,Hi15/S,Hi16/S,HiAuto/S,QU=Quiet/S,RHeight/K/N,RWidth/K/N,RTop/K/N,"
                         "RLeft/K/N,AI=AppIcon/S,IName/K,ITop/K/N,ILeft/K/N,FM=FrcMsgReq/S,PubScreen/K";

static struct {
               UBYTE  **pics;
               UBYTE   *ddir;
               UBYTE   *pat;
               LONG    *cbuf;
               LONG   nocent;
               LONG   noscrl;
               LONG   behind;
               LONG     hi15;
               LONG     hi16;
               LONG   hiauto;
               LONG    quiet;
               LONG *rheight;
               LONG  *rwidth;
               LONG    *rtop;
               LONG   *rleft;
               LONG  appicon;
               UBYTE  *iname;
               LONG    *itop;
               LONG   *ileft;
               LONG  fmsgreq;
               UBYTE *pubscr;
              } cliparams = { NULL,NULL,NULL,NULL,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,
                              FALSE,NULL,NULL,NULL,NULL,FALSE,NULL,NULL,NULL,FALSE,NULL };


/* Locale Strings */

STRPTR localstr[11];

/* Strukturen für den Picassoscreen */

struct TagItem screentags[] = { { TAVIS_SCREEN_WIDTH },
                                { TAVIS_SCREEN_HEIGHT },
	                        { TAVIS_SCREEN_DEPTH },
                                { TAVIS_OPEN_BEHIND, FALSE },
                                { TAVIS_BEST_MODEID, TRUE },
                                { TAVIS_ALLOW_FALLBACK },
                                { TAVIS_AUTOSCROLL, TRUE },
                                { TAG_DONE } };

struct TagItem modetags[] = { { TAVIS_SCREEN_WIDTH },
                              { TAVIS_SCREEN_HEIGHT },
	                      { TAVIS_SCREEN_DEPTH },
                              { TAG_DONE } };

struct NewWindow     nw;  
struct Screen *s = NULL;
struct Window *w = NULL;


/* Globale Flags */

UWORD        IFFSTATE; /* Flags für IFF */
UWORD USERFLGS = NULL; /* Programm Flags User/Privat */


/* Strukturen für das AppIcon */

struct DiskObject *appdobj = NULL;
struct MsgPort    *appport = NULL;
struct AppIcon    *appicon = NULL;
struct AppMessage  *appmsg = NULL;

static UBYTE defname[] = "ShowPicasso 1.06";
STRPTR       iconname = defname; /* Defaultname für das AppIcon */
ULONG itop = NULL, ileft = NULL; /* Positionsvariable des AppIcon */


/* Filenamenliste */

BPTR           *dirlock = NULL; /* Zeiger auf ein Array von Directory Locks bei WBStart */
STRPTR        *filename = NULL; /* Zeiger auf ein Array von Filenamen */
UBYTE             nfile = NULL; /* Anzahl der Files */


/* Programmname und Name des PubScreen */

STRPTR     mynamebuffer = NULL; /* eigener Programmname */
STRPTR       pubscrname = NULL; /* Zeiger auf Namen eines PubScreen */


/* Strukturen für ASL File Requester */

static UBYTE nullstr[]  = "";   /* Nullstring für Filerequester */
static UBYTE dpatstr[]  = "#?"; /* Defaultpatternstring für Filerequester */

STRPTR       dirname = nullstr; /* Zeiger auf Directory des Filerequester */
STRPTR       pattern = dpatstr; /* Zeiger auf Pattern des Filerequester */

struct FileRequester *freq = NULL; /* Muß auch als Zeiger für rtFileRequester herhalten */
struct RDArgs         *rda = NULL;
struct DiskObject    *dobj = NULL;

ULONG       aslh,aslw,aslt,asll; /* Angaben des User für Größe und Position des Filerequester */

struct TagItem ASLFRtags[] = { { ASLFR_TitleText, (LONG)defname },
                               { ASL_FuncFlags, FILF_MULTISELECT|FILF_PATGAD },
                               { ASL_Dir },
                               { ASL_Pattern },
                               { ASL_Height },
                               { ASL_Width },
                               { ASL_LeftEdge },
                               { ASL_TopEdge },
                               { ASLFR_Screen },
                               { TAG_DONE } };


/* Strukturen für ReqTools File Requester (alternativ) */

struct rtFileList  *flist, *tempflist;
STRPTR fname = NULL;

struct TagItem rtreqtags[] = { { RTFI_Flags, FREQF_MULTISELECT|FREQF_PATGAD },
                             { RT_Screen },
                             { TAG_DONE } };

struct TagItem rtattrtags[] = { { RTFI_Dir },
                              { RTFI_MatchPat },
                              { TAG_DONE } };

/* IFF ILBM */

struct IFFHandle *picture = NULL;
BitMapHeader        *bmhd = NULL;
UBYTE              *color = NULL;


/* Buffer für Entpackroutine */

ULONG          cbufsize = 0x4000;   /* Defaultgröße von cbuf für AllocVec() */
UBYTE               *cbuf = NULL;   /* Zwischenspeicher für gecrunchte Daten */


/* Unterroutinen */


#include "sp_protos.h"
#include "sp_catalog.c"
#include "sp_tools.c"
#include "sp_iff.c"


/* Öffnen und Schließen der Bild Datei 
**
** Gibt einen BYTE Wert zurück der das Dateiformat bestimmt.
** 0 Fehler
** 1 IFF-ILBM
** 2 IFF-RGBN
** 3 IFF-RGB8
**
*/

BYTE OpenPic(UBYTE *picname)
{
 BPTR filehandle = NULL;
 LONG error;
 BYTE type;

 if( picture = AllocIFF() )
 {

  if(filehandle = Open(picname,MODE_OLDFILE))
  {
   picture->iff_Stream = filehandle;
   InitIFFasDOS(picture);

   if(!OpenIFF(picture, IFFF_READ))
   {
    if(type = IsIFF(picture)) return(type); 
    else error = MSG_NOTKNOWN;
    CloseIFF(picture);
   }
   else error = MSG_EOPENIFF;
  }
  else error = MSG_NOFILE;
 }
 else error = MSG_EALLOCMEM;

 if(filehandle)
 { 
  Close(filehandle);
  picture->iff_Stream = NULL;
 }

 if(error) OutText(localstr[error],picname);

 return(NULL);
}

VOID ClosePic(BPTR filehandle)
{
 if(picture)
 { 
  CloseIFF(picture);
  FreeIFF(picture);
  Close(filehandle);
 }
}

/* Öffnen eines Picasso Screen */

BOOL OpenDisplay(BitMapHeader *bmap,ULONG mode)
{
 struct  DimensionInfo dimension;
 DisplayInfoHandle        handle; 

 UBYTE        sd = bmap->nPlanes;
 UWORD              sw = bmap->w;
 UWORD              sh = bmap->h;
 BOOL            TRYAGAIN = TRUE;

 if(USERFLGS & UFLG_BEHIND) screentags[3].ti_Data = TRUE; /* Screen Behind */

 if(sd == 12) sd = 15L;                 /* Screentiefe 15 Bit bei 12 Planes */
 if(USERFLGS & PFLG_TRUECLR)
 {
  if(USERFLGS & UFLG_TC15BIT) sd = 15L; /* Screentiefe 15 Bit bei Hicolor */
  if(USERFLGS & UFLG_TC16BIT) sd = 16L; /* Screentiefe 16 Bit bei Hicolor */
 }
 if(mode & HAM_KEY)
 {
  if(sd == 6) sd = 15L;                 /* Screentiefe 15 Bit bei HAM6 */
  if(sd == 8) sd = 24L;                 /* Screentiefe 24 Bit bei HAM8 */
 }

TryAgain:

 if(!(USERFLGS & UFLG_NOSCROLL))
 {
  modetags[0].ti_Data = sw;
  modetags[1].ti_Data = sh;
  modetags[2].ti_Data = sd;
  screentags[4].ti_Tag = TAVIS_SCREEN_MODEID;
  screentags[4].ti_Data = VillageBestModeID(modetags);

  if(handle = FindDisplayInfo(screentags[4].ti_Data))
  {
   if(GetDisplayInfoData(handle,(UBYTE *)&dimension,sizeof(dimension),DTAG_DIMS,TAG_DONE))
   {
    if(dimension.Nominal.MaxX+1 > sw) sw = dimension.Nominal.MaxX+1;
    if(dimension.Nominal.MaxY+1 > sh) sh = dimension.Nominal.MaxY+1;
   }
  }
 }

 screentags[0].ti_Data = sw; /* Screenweite */
 screentags[1].ti_Data = sh; /* Screenhöhe  */
 screentags[2].ti_Data = sd; /* Screentiefe */


 if(s = OpenVillageScreenTagList(screentags))
 {
  nw.LeftEdge  = 0; 
  nw.TopEdge   = 0;
  nw.Width     = s->Width;
  nw.Height    = s->Height;
  nw.FirstGadget = NULL; 
  nw.Title     = NULL;
  nw.IDCMPFlags= IDCMP_VANILLAKEY | IDCMP_MOUSEBUTTONS;
  nw.Flags     = WFLG_BACKDROP | WFLG_BORDERLESS | WFLG_RMBTRAP | WFLG_ACTIVATE;
  nw.Type      = CUSTOMSCREEN;
  nw.Screen    = s;

  if (w = OpenWindow(&nw)) return(TRUE);
 }
 else 
 {
  if(TRYAGAIN)
  {
   if((USERFLGS & PFLG_TRUECLR) && (USERFLGS & UFLG_AUTO16))
   {
    sd = 16;
    USERFLGS |= UFLG_TC16BIT;
    TRYAGAIN = FALSE;
    goto TryAgain;
   }
  }
 }
 return(FALSE);
}

VOID CloseDisplay(VOID)
{
 if(w) 
 {
  CloseWindow(w);
  w = NULL;
 }
 if(s) 
 {
  CloseVillageScreen(s);
  s = NULL;
 }
}


/* Shell bzw. WB Argumente einlesen */


VOID GetArgs(int arg,struct WBStartup *wbs)
{
 struct WBArg *wbarg;

 UBYTE   **toolarray;
 STRPTR       string;
 BPTR          olock;
 BPTR          dlock;
 register     LONG i;


 if(arg) /* Start von Shell */
 {

  if(rda = ReadArgs(templ,(LONG *)&cliparams,NULL))
  {
   if(cliparams.ddir) dirname = cliparams.ddir;
   if(cliparams.pat) pattern = cliparams.pat;
   if(cliparams.pubscr) pubscrname = cliparams.pubscr;
   if(cliparams.cbuf) cbufsize = *(cliparams.cbuf) * 1024L;
   if(cliparams.nocent) USERFLGS |= UFLG_NOCENTER;
   if(cliparams.noscrl) USERFLGS |= UFLG_NOSCROLL;
   if(cliparams.behind) USERFLGS |= UFLG_BEHIND;
   if(cliparams.hi15) USERFLGS |= UFLG_TC15BIT;
   if(cliparams.hi16) USERFLGS |= UFLG_TC16BIT;
   if(cliparams.hiauto) USERFLGS |= UFLG_AUTO16;
   if(cliparams.quiet) USERFLGS |= UFLG_QUIET;
   if(cliparams.rheight) aslh = *(cliparams.rheight);
   if(cliparams.rwidth) aslw = *(cliparams.rwidth);
   if(cliparams.rtop) aslt = *(cliparams.rtop);
   if(cliparams.rleft) asll = *(cliparams.rleft);
   if(cliparams.appicon) USERFLGS |= UFLG_APPICON;
   if(cliparams.iname) iconname = cliparams.iname;
   if(cliparams.itop)  itop = *(cliparams.itop);
   if(cliparams.ileft) ileft = *(cliparams.ileft);
   if(cliparams.fmsgreq) USERFLGS |= UFLG_FMSGREQ;
   if(cliparams.pics && !(USERFLGS & UFLG_APPICON)) /* Bei APPICON wird die Angabe von Files ignoriert */
   {
    USERFLGS |= PFLG_CLIARGS;

    FOREVER
    {
     if(!(cliparams.pics[nfile])) break;
     nfile++;
    }

    if(filename = AllocVec(4 * nfile,MEMF_PUBLIC|MEMF_CLEAR))
    {
     for(i=0; i < nfile; i++) filename[i] = cliparams.pics[i];
    }
   }
  }

 }
 else     /* Start von Workbench */
 {
  wbarg = wbs->sm_ArgList;
  dlock = wbarg->wa_Lock;
  olock = CurrentDir(dlock);
  
  if((wbarg->wa_Name) && (dobj=GetDiskObject(wbarg->wa_Name)))
  {
   toolarray = (UBYTE **)dobj->do_ToolTypes;
   if(string = FindToolType(toolarray,"DEFDIR")) dirname = string;
   if(string = FindToolType(toolarray,"PATTERN")) pattern = string;
   if(string = FindToolType(toolarray,"CBUF"))
   {
    if(!(cbufsize = 1024L * stol(string))) cbufsize = 0x4000;
   }
   if(string = FindToolType(toolarray,"RHEIGHT")) aslh = stol(string);
   if(string = FindToolType(toolarray,"RWIDTH")) aslw = stol(string);
   if(string = FindToolType(toolarray,"RTOP")) aslt = stol(string);
   if(string = FindToolType(toolarray,"RLEFT")) asll = stol(string);
   if(MatchToolValue(FindToolType(toolarray,"CENTER"),"NO")) USERFLGS |= UFLG_NOCENTER;
   if(MatchToolValue(FindToolType(toolarray,"AUTOSCROLL"),"NO")) USERFLGS |= UFLG_NOSCROLL;
   if(MatchToolValue(FindToolType(toolarray,"BEHIND"),"YES")) USERFLGS |= UFLG_BEHIND;
   if(MatchToolValue(FindToolType(toolarray,"APPICON"),"YES")) USERFLGS |= UFLG_APPICON;
   if(string = FindToolType(toolarray,"INAME")) iconname = string;
   if(string = FindToolType(toolarray,"ITOP")) itop = stol(string);
   if(string = FindToolType(toolarray,"ILEFT")) ileft = stol(string);
   if(string = FindToolType(toolarray,"HICOLOR"))
   {
    if(MatchToolValue(string,"15")) USERFLGS |= UFLG_TC15BIT;
    if(MatchToolValue(string,"16")) USERFLGS |= UFLG_TC16BIT;
    if(MatchToolValue(string,"AUTO")) USERFLGS |= UFLG_AUTO16;
   }
   if(string = FindToolType(toolarray,"PUBSCREEN")) pubscrname = string;
  }

  CurrentDir(olock);

  if((wbs->sm_NumArgs) > 1 && !(USERFLGS & UFLG_APPICON)) /* Bei APPICON werden Files als Argumente ignoriert */
  {
   USERFLGS |= PFLG_WBARGS;

   nfile = (wbs->sm_NumArgs) - 1;

   if((dirlock = AllocVec(nfile * 4,MEMF_PUBLIC|MEMF_CLEAR)) &&
      (filename = AllocVec(nfile * 4,MEMF_PUBLIC|MEMF_CLEAR)))
   {
    for(i=0; i < nfile; i++)
    {
     wbarg++;
     if(wbarg->wa_Lock) { dirlock[i] = wbarg->wa_Lock; }
     else { dirlock[i] = dlock; }
     filename[i] = wbarg->wa_Name;
    }
   }

  }
 }  
}


/* Installation des AppIcons auf der WB */


BOOL InstallAppIcon(struct WBStartup *wbs)
{
 STRPTR        myname;

 if(USERFLGS & PFLG_WBSTART)
 {
  myname = ((struct WBArg *)(wbs->sm_ArgList))->wa_Name; /* Programname aus Struktur */
 }
 else
 {
  myname = mynamebuffer;
  GetProgramName(myname,64L); /* Programname durch Funktion */
 }

 if(appdobj = GetDiskObject(myname))
 {
  appdobj->do_Type = WBAPPICON;
  appdobj->do_CurrentX = ileft;
  appdobj->do_CurrentY = itop;

  if(appport = CreateMsgPort())
  {
   if(appicon = AddAppIconA(0L,0L,iconname,appport,NULL,appdobj,NULL))
   {
    return(TRUE);
   }
  }
 }
 return(FALSE);
}


/* Entfernen des AppIcon von der WB */


VOID DeleteAppIcon(VOID)
{
 if(appicon) RemoveAppIcon(appicon);
 if(appport)
 {
  while(appmsg = (struct AppMessage *)GetMsg(appport)) ReplyMsg((struct Message *)appmsg);
  DeleteMsgPort(appport); /* Mögliche Messages auslesen, MsgPort entfernen */
 }
 if(appdobj) FreeDiskObject(appdobj);
}


/* ASL Filerequester */


BOOL FileRequest(VOID)
{
 struct Screen *pubscr;
 struct WBArg  *frargs;

 ULONG  rheight = 400L;
 ULONG   rwidth = 318L;
 ULONG      rleft,rtop;
 BOOL    error = FALSE;
 register       LONG i;

 if(pubscr = LockPubScreen(pubscrname))
 {

  if(!freq)
  {

   if(ReqToolsBase)
   {

    if(freq = (struct FileRequester *)rtAllocRequestA(RT_FILEREQ,NULL))
    {
     rtreqtags[1].ti_Data = (LONG)pubscr;
     rtattrtags[0].ti_Data = (LONG)dirname;
     rtattrtags[1].ti_Data = (LONG)pattern;
     rtChangeReqAttrA((struct rtFileRequester *)freq, rtattrtags);
    }
    
   }
   else
   {

    if(aslh)
    {
     rheight = aslh; /* Benutzerwert für Requesterhöhe übernehmen */
     if(rheight < 155) rheight = 155L;
    }
    else
    {
     if(pubscr->Height <= 400) rheight = 200L; /* Defaultwerte */
    }

    if(aslw)
    {
     rwidth = aslw; /* Benutzerwert übernehmen; Default Requesterweite ist 318 */
     if(rwidth < 262) rwidth = 262L;
    }

    if(asll) rleft = asll;  /* Benutzerwert für Left Position übernehmen */
    else rleft = (pubscr->Width -  rwidth) / 2;  /* Default: Requester in der Mitte zentriert. */

    if(aslt) rtop = aslt; /* Benutzerwert für Top Position übernehmen */
    else rtop  = (pubscr->Height - rheight) / 2; /* -''- */

    ASLFRtags[2].ti_Data = (LONG)dirname; /* Parameter in die Tags schreiben */
    ASLFRtags[3].ti_Data = (LONG)pattern;
    ASLFRtags[4].ti_Data = rheight;
    ASLFRtags[5].ti_Data = rwidth;
    ASLFRtags[6].ti_Data = rleft;
    ASLFRtags[7].ti_Data = rtop;
    ASLFRtags[8].ti_Data = (LONG)pubscr;

    /* Abfrage auf Workbench 2.1, wenn ja, kann Requester auf jedem Pubscreen öffnen */

    if((AslBase->lib_Version) < 38L) ASLFRtags[8].ti_Tag = TAG_DONE; 

    freq = (struct FileRequester *)AllocAslRequest(ASL_FileRequest,ASLFRtags);
   }

  }

  if(freq)
  {

   if(ReqToolsBase)
   {

    if(flist = rtFileRequestA((struct rtFileRequester *)freq, fname, defname, rtreqtags))
    {
     tempflist = flist;
     nfile = 0L;
     while( tempflist ) { nfile++; tempflist = tempflist->Next; }
     tempflist = flist;
     dirname = ((struct rtFileRequester *)freq)->Dir;

     if(filename = AllocVec(4 * nfile,MEMF_PUBLIC|MEMF_CLEAR))
     {
      for(i=0; i < nfile; i++) 
      {
       filename[i] = tempflist->Name;
       tempflist = tempflist->Next;
      }
     }

    }
    else error = TRUE;

   }
   else
   {

    if(AslRequest(freq,NULL))
    {

     if(nfile = freq->rf_NumArgs)
     {
      frargs = freq->rf_ArgList;
      dirname = freq->rf_Dir;

      if(filename = AllocVec(4 * nfile,MEMF_PUBLIC|MEMF_CLEAR))
      {
       for(i = 0; i < freq->rf_NumArgs; i++) filename[i] = frargs[i].wa_Name;
      } 
     } 
    }
    else error = TRUE;

   }

  }
  else error = TRUE;

  UnlockPubScreen(NULL,pubscr);
 }
 else
 {
  OutText(localstr[MSG_NOPUBSCR],NULL);
  error = TRUE;
 }

 return(error);
}


/* Anzeigen des Bildes bzw. der Bilder */


VOID ViewPicture(STRPTR *picfilename, STRPTR picdirname, BPTR *picdirlock)
{
 struct      Message *msg;
 struct  ContextNode *top;

 BPTR         dlock,olock; /* Lock des aktuellen, bzw. alten Verzeichnisses */
 BYTE            datatype; /* Art des IFF Files */
 ULONG             modeid;
 ULONG             ncolor; /* Anzahl der Farben */

 LONG               error;
 LONG     filecnt,size[4];

#ifdef TIME

 clock_t                 t1,t2;

#endif

 register LONG             i,j;

 if(filename)
 {

  if(dirname) dlock = Lock(dirname,ACCESS_READ); 

  for(filecnt=0; filecnt < nfile; filecnt++)
  {
   IFFSTATE = NULL;
   USERFLGS &= 0xfeff;

   if(USERFLGS & UFLG_AUTO16) USERFLGS &= 0xf0ff; /* Falls "HICOLOR=AUTO" Hicolor Bits  wieder löschen */

   if(USERFLGS & PFLG_WBARGS) { olock = CurrentDir(dirlock[filecnt]); }
   else { if(dirname) olock = CurrentDir(dlock); }

   if(datatype = OpenPic(filename[filecnt]))
   {

    switch(datatype)
    {
     case 1:

     IFFSTATE |= ILBMFLG;
     break;

     case 2:

     IFFSTATE |= RGBNFLG;
     break;

     case 3:

     IFFSTATE |= RGB8FLG;
     break;
    }

    FOREVER
    {
     error=ParseIFF(picture,IFFPARSE_RAWSTEP);

     if(error == IFFERR_EOC) continue;
     else if(error) error = MSG_MIFFILBM;

     if(top=CurrentChunk(picture))
     {

      if((top->cn_ID) == ID_BMHD)
      {
       if(IFFSTATE & BMHDFLG) error = MSG_CHKEXIST2;
       else
       {
        if(GetBMHD(picture,bmhd))
        {
         if(bmhd->nPlanes == 13)                 /* Pseudo 13 für RGBN */
         {
          bmhd->nPlanes = 12;
         }
         if(bmhd->nPlanes == 24) USERFLGS |= PFLG_TRUECLR;
         if(bmhd->nPlanes == 25)                 /* Pseudo 25 für RGB8 */
         {
          USERFLGS |= PFLG_TRUECLR;
          bmhd->nPlanes = 24;
         }
        }
        else error = MSG_MIFFILBM;
        IFFSTATE |= BMHDFLG;
       }
       ncolor = 1L<<bmhd->nPlanes;
      }

      if((top->cn_ID) == ID_CAMG) 
      {
       if(IFFSTATE & CAMGFLG) error = MSG_CHKEXIST2;
       else
       {
        if(GetCAMG(picture,&modeid))
        {
         if(modeid & EXTRAHALFBRITE_KEY)
         {
          ncolor = 32;
         }
         if(modeid & HAM_KEY)
         {
          if(bmhd->nPlanes == 6) ncolor = 16;
          if(bmhd->nPlanes == 8) ncolor = 64;
         }
        }
        else error = MSG_MIFFILBM;
        IFFSTATE |= CAMGFLG;
       }
      }

      if((top->cn_ID) == ID_CMAP)
      {
       if(IFFSTATE & CMAPFLG) error = MSG_CHKEXIST2;
       else
       {
        if(!((USERFLGS & PFLG_TRUECLR) || (IFFSTATE & RGBNFLG)))
        {
         if(!GetCMAP(picture,color,ncolor)) error = MSG_MIFFILBM;
        }
        IFFSTATE |= CMAPFLG;
       }
      }

      if((top->cn_ID) == ID_BODY)
      {
       if((IFFSTATE & BMHDFLG) && ((USERFLGS & PFLG_TRUECLR) || (IFFSTATE & CMAPFLG) || (IFFSTATE & RGBNFLG))) break;
       else error = MSG_MIFFILBM;
      }
     }
     if(error) break;
    }

#ifdef TIME

    t1=clock(); /* ANSI Clock Function */

#endif

    if((!error) && OpenDisplay(bmhd,modeid))
    {

     /* Kein Error nur möglich wenn BODY Chunk gefunden 
        Auslesen der Chunk Daten, konvertieren und in   
        die Bitmap schreiben. Farbregister setzen */

     if((IFFSTATE & CMAPFLG) && !(USERFLGS & PFLG_TRUECLR))
     {
      j=0;         

      Delay(2L);

      /* Without the Delay() function the color registers will not be correctly set.
         This seems to be a bug in the firmware */
         

      /* Das seltsame j<<(8-bmhd->nPlanes) kommt durch die seltsame
         Planar => Chunky Konvertierung zustande (Assembler). */

      for(i=0; i <= (3*ncolor-3); i += 3)
      {
       SETRGB(s,j<<(8-bmhd->nPlanes),color[i],color[i+1],color[i+2]);
       j++;
      }

      if(modeid & EXTRAHALFBRITE_KEY)
      {
       for(i=0; i <= (3*ncolor-3); i += 3)
       {
        SETRGB(s,j<<(8-bmhd->nPlanes),color[i]>>1L,color[i+1]>>1L,color[i+2]>>1L);
        j++;
       }
      }
     }

     if(IFFSTATE & ILBMFLG)
     {
      error = GetBODY_ILBM(picture,bmhd,modeid,s);
     }
     else
     {
      error = GetBODY_RGBx(picture,bmhd,s);
     }

     if(USERFLGS & UFLG_BEHIND) ScreenToFront(s);

#ifdef TIME

     t2 = clock();

#endif

     if(!error)
     {
      Wait(WSig);
      while(msg = GetMsg(w->UserPort)) 
      {
       ReplyMsg(msg);
      }
     }
    }
    else if(!error) error = MSG_NOSCR;
    CloseDisplay();

    if(error == USR_BREAK) break;
    else if(error) OutText(localstr[error],filename[filecnt]); /* Ausgabe der Fehlermeldung */

    if(!error && !(USERFLGS & (UFLG_QUIET | PFLG_WBSTART))) 
    {
     size[0] = (LONG)filename[filecnt];
     size[1] = bmhd->w;
     size[2] = bmhd->h;
     size[3] = bmhd->nPlanes;
     VPrintf("%s : %ldx%ldx%ld\n",size);

#ifdef TIME
   
     t1 = t2 - t1;
     VPrintf("%ld ticks\n",&t1);

#endif
        
    }

    ClosePic(picture->iff_Stream);
   }

   if(USERFLGS & PFLG_WBARGS) { CurrentDir(olock); }
   else { if(dirname) CurrentDir(olock); }
  }

  if(dirname) UnLock(dlock);
  if(dirlock) FreeVec(dirlock);
  if(flist)   rtFreeFileList(flist); /* Bei Verwendung der ReqTools Requester freigabe von flist */
   
  FreeVec(filename);
  dirlock = NULL;
  filename = NULL;
 }
}


/* Hauptprogramm */


VOID main(int argc,struct WBStartup *wbs)
{
 BOOL    done = FALSE;
 BOOL APPICON = FALSE;
 register LONG      i;

 if(OpenLibs())
 {

  if(LocaleBase)
  {
   catalog = OpenCatalogA(NULL,"showpicasso.catalog",NULL);
   for(i = 0; i < 10L; i++) localstr[i+1] = GetString(i);
  }

  if(!argc) USERFLGS |= PFLG_WBSTART;
  GetArgs(argc,wbs);

  if(GetWorkSpace())
  {

   if(USERFLGS & UFLG_APPICON) APPICON = InstallAppIcon(wbs);

   do
   {

    if(APPICON)
    {

     WaitPort(appport);
     while(appmsg = (struct AppMessage *)GetMsg(appport))
     {
      if(appmsg->am_NumArgs == NULL)
      {
       done = FileRequest();
       ViewPicture(filename, dirname, dirlock);
      }
      else if(appmsg->am_NumArgs > NULL)
      {
       nfile = appmsg->am_NumArgs;
       if((dirlock = AllocVec(nfile * 4,MEMF_PUBLIC|MEMF_CLEAR)) &&
          (filename = AllocVec(nfile * 4,MEMF_PUBLIC|MEMF_CLEAR)))
       {
        for(i=0; i < nfile; i++)
        {
         dirlock[i] = appmsg->am_ArgList[i].wa_Lock;
         filename[i] = appmsg->am_ArgList[i].wa_Name;
        }
       }
       done = FALSE;
       USERFLGS |= PFLG_WBARGS;
       ViewPicture(filename, dirname, dirlock);
      }
      ReplyMsg((struct Message *)appmsg);
     }
     USERFLGS &= 0x1fff;

    }
    else
    {

     if(USERFLGS & (PFLG_CLIARGS | PFLG_WBARGS))
     {
      done = TRUE;
      ViewPicture(filename, dirname, dirlock);
     }
     else
     {
      done = FileRequest();
      ViewPicture(filename, dirname, dirlock);
     }

    }

   } while(!done);

   if(USERFLGS & UFLG_APPICON) DeleteAppIcon(); /* AppIcon entfernen */
   if(dobj) FreeDiskObject(dobj);
   if(freq) 
   {
    if(ReqToolsBase) rtFreeRequest((struct rtFileRequester *)freq);
    else FreeAslRequest(freq);
   }
   if(rda) FreeArgs(rda);

   FreeWorkSpace();
  }
  else OutText(localstr[MSG_EALLOCMEM],NULL);
 }
 else OutText(localstr[MSG_EOPENLIBS],NULL);
 CloseLibs();
}
