/**********************************************(*************************/
/* Beispielprogramm zum C-Kurs, Folge 10, in der GetiT                  */
/* Programmiert von Peter Fischer, RP.-Ebert-Str. 6, 3257 Springe 1     */
/* Telefon : 05041/63563, am besten nach 20:30 Uhr.                     */
/*                                                                      */
/* Dieses Programm geht unter die Gürtellinie des Programmierens        */
/* und sollte nicht als Beispiel für gutes Programmieren angesehen      */
/* werden !                                                             */
/*                                                                      */
/* Eigentlich sollte ich nicht, aber trotzdem ist diese Programm        */
/* PUBLIC DOMAIN !                                                      */
/*                                                                      */
/* Ich werde NICHT jede kleine Zuweisung kommentieren. Wer nicht        */
/* durchsteigt, sollte mich entweder anrufen, mir eine Postkarte        */
/* schicken oder die Finger von dem Programm lassen !                   */
/************************************************************************/

/* Einladen der Include-Files */
#include <exec/types.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <libraries/arpbase.h>

/* Zeiger auf die Standardlibraries ! */
struct IntuitionBase *IntuitionBase;
struct GfxBase       *GfxBase;
struct ArpBase       *ArpBase;

/* Zeiger auf wichtige Größen. */
struct RastPort *rp;

/* Ports und Tasks */
struct MsgPort *winport;
struct Task *wintask;

/* Für Intuition */
struct Window *win;
struct Screen *screen;
struct IntuiMessage *msg;

struct NewScreen ns =
{ 0,0,640,256,4,0,1,HIRES,CUSTOMSCREEN,NULL,"NIX",NULL };

struct NewWindow nw =
{ 0,0,640,10,0,1,
  CLOSEWINDOW | VANILLAKEY, ACTIVATE | WINDOWCLOSE,
  NULL,NULL,"PLANE",NULL,NULL,0,0,0,0,CUSTOMSCREEN
};

/* Definition der Bitmap, siehe text. */
struct BitMap 
  bm = { 0,0,0,0,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL },
  dm = { 0,0,0,0,0,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL };

/* Für den Zufallszahlengenerator. Auch nicht schön, greift auf eine */
/* feste Adresse im System zu !                                      */
/* Wer weiß schon, auf was diese Adresse unter WB v1.4 zeigt ?       */
unsigned int *seed = (unsigned int *)0xdff006;

main()
{ int i;
  register int x, v, w, o;
  char aus[100];
  BYTE *p;

  /* Öffnen der Library */
  ArpBase = OpenLibrary ( "arp.library",0 );
  if ( ArpBase == NULL )
    raus();
  /* Alle anderen Zeiger abholen. */
  IntuitionBase = ArpBase->IntuiBase;
  GfxBase = ArpBase->GfxBase;

  /* Öffnen des Screens */
  screen = OpenScreen ( &ns );
  if ( screen == NULL )
    raus();
  /* Öffnen des Fensters */
  nw.Screen = screen;
  win = OpenWindow ( &nw );
  if ( win == NULL )
    raus();
  /* Wichtige Zeiger abholen */
  rp = &screen->RastPort;
  winport = win->UserPort;
  wintask = winport->mp_SigTask;

  /* Festlegen der Bitmap-Werte */
  dm.BytesPerRow = bm.BytesPerRow = rp->BitMap->BytesPerRow;
  dm.Rows        = bm.Rows        = rp->BitMap->Rows;
  dm.Flags       = bm.Flags       = rp->BitMap->Flags;
  dm.Depth       = bm.Depth       = rp->BitMap->Depth;
  dm.pad         = bm.pad         = rp->BitMap->pad;
  for ( i = 0; i < 8 && rp->BitMap->Planes[i] != NULL; i++ )
  { bm.Planes[i] = AllocMem ( rp->BitMap->Rows * rp->BitMap->BytesPerRow,MEMF_CHIP | MEMF_CLEAR );
    if ( bm.Planes[i] == NULL )
      raus();
  }
  for ( i = 0; i < 8 && rp->BitMap->Planes[i] != NULL; i++ )
  { dm.Planes[i] = AllocMem ( rp->BitMap->Rows * rp->BitMap->BytesPerRow,MEMF_CHIP | MEMF_CLEAR );
    if ( dm.Planes[i] == NULL )
      raus();
  }

  /* Ausgabe der Bedienungsanleitung auf den Bildschirm. */
  Ausg ( "Testprogramm. Zuerst werden einige Daten ausgegeben. Weiter : Close-Gadget " );
  Ausg ( "anklicken. Dann wird der Screen eingefärbt. Wieder mit Close-Gadget " );
  Ausg ( "weiter, hier wird nicht gewartet ! ( Endlosschleife ! ) Nun wird eine " );
  Ausg ( "andere Bitmap dargestellt. Auch wenn hier das Close-Gadget verschwindet, " );
  Ausg ( "muß es gedrückt werden ! Dann wird wieder der Originalbildschirm " );
  Ausg ( "aufgebaut. Mit Close-Gadget wird das Programm beendet ! " );
  Ausg ( "Alternativ zum Close-Gadget kann auch beliebige Taste gedrückt werden !" );
  Ausg ( "Kommentar siehe beiligenden Text ! " );

  /* Ausgabe der Werte auf den Bildschirm. */
  sprintf ( aus,"&BitMap : %lx\n",rp->BitMap );
  Ausg ( aus );
  sprintf ( aus,"  BytesPerRow : %d\n",rp->BitMap->BytesPerRow );
  Ausg ( aus );
  sprintf ( aus,"  Rows        : %d\n",rp->BitMap->Rows );
  Ausg ( aus );
  sprintf ( aus,"  Flags       : %d\n",rp->BitMap->Flags );
  Ausg ( aus );
  sprintf ( aus,"  Depth       : %d\n",rp->BitMap->Depth );
  Ausg ( aus );
  sprintf ( aus,"  pad         : %d\n",rp->BitMap->pad );
  Ausg ( aus );
  sprintf ( aus,"  &Planes[0]  : %lx\n",rp->BitMap->Planes[0] );
  Ausg ( aus );
  sprintf ( aus,"  &Planes[1]  : %lx\n",rp->BitMap->Planes[1] );
  Ausg ( aus );
  sprintf ( aus,"  &Planes[2]  : %lx\n",rp->BitMap->Planes[2] );
  Ausg ( aus );
  sprintf ( aus,"  &Planes[3]  : %lx\n",rp->BitMap->Planes[3] );
  Ausg ( aus );
  sprintf ( aus,"  &Planes[4]  : %lx\n",rp->BitMap->Planes[4] );
  Ausg ( aus );
  sprintf ( aus,"  &Planes[5]  : %lx\n",rp->BitMap->Planes[5] );
  Ausg ( aus );
  sprintf ( aus,"  &Planes[6]  : %lx\n",rp->BitMap->Planes[6] );
  Ausg ( aus );
  sprintf ( aus,"  &Planes[7]  : %lx\n",rp->BitMap->Planes[7] );
  Ausg ( aus );

  /* Warten auf Reaktion der Users. */
  Wait ( 1 << win->UserPort->mp_SigBit );
  msg = GetMsg ( win->UserPort );
  if ( msg != NULL )
    ReplyMsg(msg);

  /* Zufallszahlengenerator mit Zahl füttern. */
  srand(*seed);
  /* Zufällig Bits auf der Bitmap setzen. Solange, bis Close-Gadget */
  /* oder Taste gedrückt wird.                                      */
  while ( ! ( wintask->tc_SigRecvd & ( 1 << winport->mp_SigBit ) ) )
  { p = (BYTE *) rp->BitMap->Planes[rand()%rp->BitMap->Depth];
    x = rand() & 255;
    w = rand() % rp->BitMap->Rows;
    v = rand() % rp->BitMap->BytesPerRow;
    *(p + w * rp->BitMap->BytesPerRow + v) = x;
  }

  /* Message wieder sauber zurückgeben. */
  msg = GetMsg ( win->UserPort );
  if ( msg != NULL )
    ReplyMsg(msg);

  /* Nochmals warten, damit man sich in Ruhe das Ergebnis anschauen kann. */
  Wait ( 1 << win->UserPort->mp_SigBit );
  msg = GetMsg ( win->UserPort );
  if ( msg != NULL )
    ReplyMsg(msg);

  /* Blit-Operationen durchführen ! */
  /* Alles auf Reserve-BitMap */
  BltBitMap ( rp->BitMap,0,0,&dm,0,0,rp->BitMap->BytesPerRow * 8,rp->BitMap->Rows,0xC0,0xff,NULL );
  /* Teile wieder zurückkopieren. */
  BltBitMap ( rp->BitMap,10,10,&bm,50,50,60,40,0x30,0xff,NULL );
  BltBitMap ( rp->BitMap,10,10,&bm,120,60,60,40,0x50,0xff,NULL );
  BltBitMap ( rp->BitMap,10,10,&bm,180,90,60,40,0xC0,0xff,NULL );
  /* Alles auf Screen-BitMap. */
  BltBitMap ( &bm,0,0,rp->BitMap,0,0,rp->BitMap->BytesPerRow * 8,rp->BitMap->Rows,0xC0,0xff,NULL );

  /* Warten auf Ereignis. */
  Wait ( 1 << win->UserPort->mp_SigBit );
  msg = GetMsg ( win->UserPort );
  if ( msg != NULL )
    ReplyMsg(msg);

  /* Original wieder zurückholen. */
  BltBitMap ( &dm,0,0,rp->BitMap,0,0,rp->BitMap->BytesPerRow * 8,rp->BitMap->Rows,0xC0,0xff,NULL );

  /* Warten bis zum bitteren Ende. */
  Wait ( 1 << win->UserPort->mp_SigBit );
  msg = GetMsg ( win->UserPort );
  if ( msg != NULL )
    ReplyMsg(msg);

  /* Adieu ! */
  raus();
}

raus()
{ int i;

  /* Alles schließen und freigeben ! */
  if ( win != NULL )
    CloseWindow ( win );
  if ( screen != NULL )
    CloseScreen ( screen );
  for ( i = 0; i < 8; i++ )
  { if ( bm.Planes[i] != NULL )
      FreeMem ( bm.Planes[i],rp->BitMap->Rows * rp->BitMap->BytesPerRow );
    if ( dm.Planes[i] != NULL )
      FreeMem ( dm.Planes[i],rp->BitMap->Rows * rp->BitMap->BytesPerRow );
  }
  if ( ArpBase != NULL )
    CloseLibrary ( ArpBase );
  exit(0);
}

/* Ausgaberoutine. */
Ausg ( txt )
char *txt;
{ static int y = 20;

  Move ( rp,10,y );
  Text ( rp,txt,strlen(txt)-1 );
  y += 10;
}
