/*************************************************************************
/*                                                                       *
/* C-Beispielprogramm für die Get-It ( Diskettenmagazin der AIT-UG )     *
/* geschrieben von Peter Fischer, RP.-Ebert-Str. 6, D-3257 Springe 1     *
/*                                                                       *
/* Kurs 5 : ARP                                                          *
/* Datum : 1.5.89                                                        *
/*                                                                       *
/* Copyrights (c)'89 by PeeF.                                            *
/* Der ausführbare Code ist Public Domain in bester Manier.              *
/* Der Quellcode darf von jedem/r GetiT-Leser/in benutzt werden, wie es  *
/* in seinem/ihrem Interesse liegt. NUR : Wenn Ihr wesentliche Teile     *
/* kopiert, so erwähnt, daß der Teil von mir stammt. Okay ?              *
/*                                                                       *
/*************************************************************************/

#include <intuition/intuition.h>
#include <exec/exec.h>
#include <graphics/gfx.h>
#include <stdio.h>
#include <libraries/arpbase.h>

/* Für AmigaDOS & Co                                                     */

extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct DiskfontBase *DiskfontBase;
extern struct ArpBase *ArpBase;

/* Selbstdarstellung des Programms                                       */
extern struct Screen *Scr;
extern struct Window *Fenster;
extern struct RastPort *rp;

/* Für Warteschleifen                                                    */
extern struct IntuiMess *mess;

/* Hier stehen am Ende des Requesters die Namen des Files und Dirs drin  */
char filename[ FCHARS ] = "beispiel.dat";
char dirname [ DSIZE + 1 ] = "";

/* Eigentliche Struktur des Requesters. Einige Werte müssen dann noch	*
 * zur Laufzeit vereinbart werden.	*/
struct FileRequester
myrequester = { "Hallo C-Kurs-Leser !",&filename[0],&dirname[0],NULL,
                NULL,NULL,NULL,NULL };

/* Der gesamte Filename mit ausgewähltem Pfad wird abgespeichert. Die 	*
 * Initialisierung dient hier der Default-Einstellung beim Öffnen des    *
 * Files !	*/
char komplett[ FCHARS + DSIZE + 1 ] = "beispiel.dat", *k;

/* Ein Gadget, das den Pattern abfragt. Nicht perfekt, aber besser als   *
 * nix. Übrigens auch ein Beispiel für eine Border vorhanden !           */
USHORT pairs[] = { -1,-1, 201,-1, 201,11, -1,11, -1,-1 };

struct Border border =
{ 0,0,1,6,JAM1,5,&pairs[0],NULL };

char undo[120];

struct StringInfo strinfo =
{ NULL,&undo[0],0,100,0,0,0,0,0,0,NULL,0,NULL };

struct Gadget inp =
{ NULL,50,3,200,20,GADGHCOMP,STRINGCENTER | RELVERIFY,
  STRGADGET,&border,NULL,NULL,NULL,&strinfo,0,0
};

/* Abweichung vom Kurs : In letzter Minute habe ich doch noch die 	*
 * Möglichkeit mit der Funktion ausprobiert. Allerdings ohne Flag.       */
quit( x,y )
LONGBITS x;
CPTR y;
{}

/* Unterprogramm, das den Requester bedient und verarbeitet.	*/
fr()
{ /* Die restlichen Initilisierungen für den Requester.	*/
  myrequester.fr_Window = Fenster;
  /* Abweichung vom Kurs : Dem Requester wird die Adresse der Funktion   *
   * mitgeteilt.	*/
  myrequester.fr_Function = (&quit)();
  /* Der große Augenblick : Er wird aufgerufen.	*/
  k = FileRequest ( &myrequester );
  if ( k != NULL ) /* Ist k NULL, dann wurde gecancelt.	*/
  { if ( *myrequester.fr_Dir != '\0' ) /* Wurde ein Dir angewählt ?      */
    { /* Dann alles zusammenfügen : fr_Dir + '/' + fr_File	*/
      strcpy ( komplett,myrequester.fr_Dir );
      strcat ( komplett,"/" );
      strcat ( komplett,myrequester.fr_File );
    }
    else                               /* Sonst nur Filename.            */
      strcpy ( komplett,myrequester.fr_File );
  }
  /* Keine Abfrage nach Rückkehr ins Hauptprogramm.                      */
  return ( TRUE );
}

/* Unterprogramm, das für die Patterns verantwortlich ist.               */
patterns()
{ /* Die Vereinbarungen für Files, steht in <stdio.h>.	*/
  FILE *fopen(),*fd;
  /* Strings für Pattern.	*/
  char zwischen[120], ausgabe[120], patt[120], prepatt[120];

  /* File öffnen.	*/
  fd = fopen( komplett,"r" );
  /* File nicht vorhanden ? Dann raus.	*/
  if ( fd == NULL )
    return( TRUE );
  /* Initialisationsroutine für Schreiben ins Fenster.	*/
  Write_to_Fenster ( NULL,NULL );
  /* Bekanntgabe.	*/
  SetWindowTitles ( Fenster,"Eingabe des Patternstrings",-1 );
  /* Dem Gadget die Bufferadresse für String mitteilen.	*/ 
  strinfo.Buffer = &patt[0];
  /* Gadget in Liste einordnen.	*/
  AddGadget ( Fenster,&inp,-1 );
  /* Nun wird Gadget gezeichnet 	*/
  RefreshGadgets ( &inp,Fenster,NULL );
  /* und aktiviert. */
  ActivateGadget ( &inp,Fenster,NULL );
  /* Warten auf die Fertig-Nachricht. ( Also auf ein RET im Gadget. )	*/
  get_mess( GADGETUP );
  /* Weg mit dem Gadget.	*/
  RemoveGadget ( Fenster,&inp );
  /* Und neuen Fenstertitel.	*/
  SetWindowTitles ( Fenster,"Passende Strings",-1 );
  /* Fenster löschen.	*/
  Move ( rp,0,0 );
  SetBPen ( rp,0 );
  ClearScreen ( rp );

  /* Abweichung vom Kurs : Hier keine Abfrage mehr !	*/
  /* Pattern vorbereiten :	*/
  PreParse ( patt,prepatt );
  /* Solange noch nicht EOF...	*/
  while ( get_zeile ( fd,zwischen,120 ) )
  { /* ... und Pattern paßt ...	*/
    if ( PatternMatch ( prepatt,zwischen ) )
      /* ...wird ausgegeben.	*/
      Write_to_Fenster ( rp,zwischen );
  }
  /* File schließen.	*/
  fclose ( fd );
  /* Taste drücken.	*/
  get_mess( RAWKEY );
  /* Und raus.	*/
  return ( FALSE );
}

/* Liest Zeile aus File mit Descriptor fd. Wird in String str abgelegt.  *
 * Maximale Länge max.	*/
get_zeile ( fd,str,max )
FILE *fd;
char str[];
int max;
{ int i = 0;
  char c;

  while ( ( c = getc ( fd ) ) != EOF && c != '\12' && i < max )
  /* Einlesen :    ^^ End-Of-File ^^    ^^ RET ^^     ^^ Bereichsüberschr.*/
    str[i++] = c;
  /* End-Of-Line */
  str[i] = '\0';
  /* EOF ? Dann nicht wieder kommen !	*/
  if ( c == EOF )
    return ( FALSE );
  return ( TRUE );
}

/* Schreibt den String str ins Fenster ( oder innen Screen ) mit 	*
 * RastPort rp. str == rp == NULL : Initialisierung	*/
Write_to_Fenster ( rp,str )
struct RastPort *rp;
char str[];
{ /* Static-Variable : Behält Wert auch nach Rückkehr aus Unterprogramm.	*/
  static int y;

  /* Initialisierung.	*/
  if ( rp == NULL )
  { y = 22;
    return ();
  }

  /* Schreibfarbe setzen.	*/
  SetAPen ( rp,3 );
  SetDrMd ( rp,JAM1 );
  /* Offset, Abstand eine Zeile + ein bißchen Abstand.	*/
  y += 10;
  /* Rand erreicht ?	*/
  if ( y > 230 )
  { /* Schieben.   	*/
    ScrollRaster ( rp,-10,10,2,23,636,240 );
    /*                ^^^ ist verantwortlich fürs Diagonalschieben.      *
     * Nur vertikal, dann 0 einsetzen !	*/
    /* Offset wieder rückgängig machen !	*/
    y -= 10;
  }
  /* Zeichencursor setzen	*/
  Move ( rp,10,y );
  /* Und schreiben.	*/
  Text ( rp,str,strlen(str) );
}

/* Wartet auf Message.	*/
get_mess( flags )
ULONG flags;
{ struct IntuiMessage *mess;
  ULONG class, oldflags;

  /* Alte IDCMP-Flags sichern.	*/
  oldflags = Fenster->IDCMPFlags;
  /* Neuen Flags einsetzen. CLOSEWINDOW für Abbruch.	*/
  ModifyIDCMP ( Fenster,flags | CLOSEWINDOW );
  /* Warten, das was passiert.	*/
  Wait ( 1 << Fenster->UserPort->mp_SigBit );
  /* Hurra, es ist was passiert !!	*/
  mess = GetMsg( Fenster->UserPort );
  /* Art der Message übernehmen.	*/
  class = mess->Class;
  /* Und wieder zurückgeben.	*/
  ReplyMsg(mess);
  /* Alte Flags wieder einsetzen.	*/
  ModifyIDCMP ( Fenster,oldflags );
  /* Und bei CLOSEWINDOW abbrechen. Aber nicht, wenn flags CLOSEWINDOW   *
   * war. Dann wartet man ja auf Ereignis !	*/
  if ( class == CLOSEWINDOW && ( flags & ~CLOSEWINDOW ) )
    notaus ( "BREAK" );
  /* Art zurück.	*/
  return(class);
}
