/*********************************************************
 * Time Disk Bestellungsprogramm für die Time.guide		*
 *				(Mein allererstes C Programm)						*
 *********************************************************
 * Autor:					Manfred Tremmel						*
 * Programmiersprache:	C											*
 * Compilier:				Maxon C++ (ANSI-C-Modus)			*
 *********************************************************/

/* Versionsstring festlegen (fürs Shellkomando Version)	*/ 
char VersionID[] = "$VER: T_Bestellen 1.33 (05.03.95)\0";

/* C-Include für String-Operationen								*/
#include <string.h>
/* C-Include für Dateioperationen (laden, speichern)		*/
#include <stdio.h>

/* AMIGA-Includes für die Exec.library							*/
#include <clib/exec_protos.h>
#include <exec/memory.h>
/* AMIGA-Include für die AmigaGuide.library					*/
#include <clib/amigaguide_protos.h>
/* AMIGA-Include für die graphics.library						*/
#include <clib/graphics_protos.h>
/* AMIGA-Include für die intuition.library					*/
#include <clib/intuition_protos.h>
/* AMIGA-Include für die gadtools.library						*/
#include <clib/gadtools_protos.h>
/* AMIGA-Include für die asl.library							*/
#include <clib/asl_protos.h>

/* AMIGA-Include, das die ganzen pragma/#? included		*/
#include <pragma/all_lib.h>

/* AMIGA-Include, daß das Programm WB-Startfähig macht	*/
#include <wbstartup.h>

/* Structur für die Intuition.library							*/
struct IntuitionBase	*IntuitionBase		= NULL;
/* Structur für die graphics.library							*/
struct GfxBase			*GfxBase				= NULL;
/* Structur für die gadtools.library							*/
struct Library			*GadToolsBase		= NULL;
/* Structur für die AmigaGuide.library							*/
struct Library			*AmigaGuideBase	= NULL;
/* Structur für die Asl.library									*/
struct Library			*AslBase				= NULL;

/* Structur für den Asl-Filerequester							*/
struct FileRequester	*fr;
/* Structru für einen einfachen Info-Requester				*/
struct EasyStruct		es;


/* Dient dazu, eine neue Liste anzulegen						*/
void NewList(struct List *);

/* OS 3.x indikator NOS (New Operating System)				*/
BOOL NOS = FALSE;

/* Globale Variablen definieren									*/
/* Einstellungen:														*/
struct Einst {
	char AName[30];			/* Absender:	Name				*/
	char AStrasse[30];		/* Absender:	Straße			*/
	char AOrt[30];				/* Absender:	Ort				*/
	char EName[30];			/* Empfänger:	Name				*/	
	char EStrasse[30];		/* Empfänger:	Straße			*/
	char EOrt[30];				/* Empfänger:	Ort				*/
	long Abstand;				/* Druckbeginnabstand			*/
	UWORD Versart;				/* Versandart						*/
	char KundNr[30];			/* Absender:	Kundennummer	*/
};

struct Einst P1;				/* Konkrete Strukt. festlegen	*/

/* Struktur der Diskettenliste (nur der Diskettenname)	*/
struct VDB{
	char Name[15];				/* Diskettennamen					*/
};

/* Structur zur Verwaltung der Diskettenliste anlegen		*/
struct VDBnode{
	struct	Node n;
	struct	VDB  d;
};

/* erzeugt eine Liste, in die die einzelen VDBs kommen	*/
struct List vdblist;

/* vdblist enthält den aktuellen Eintrag oder NULL			*/
struct VDBnode *currentvdb;

/* Filename fürs Abspeichern der Druckdatei					*/
char filename[80] = "ram:T_Druck";

/* Dateiname des Einstellungs-Files								*/
char Einst_File[] = "T_Best.dat";

/* Funktion GetString holt einen Text aus dem Puffer		*/
#define GetString( g )	((( struct StringInfo * )g->SpecialInfo )->Buffer  )
/* Funktion GetNumber holt eine Nummer aus dem Puffer		*/
#define GetNumber( g )	((( struct StringInfo * )g->SpecialInfo )->LongInt )

/* Die Nummern der Gadgets mit konkreten Bezeichnung		*/
#define GD_Diskliste		0		/* Diskettenliste				*/
#define GD_NeueDisk		1		/* Neu Button					*/
#define GD_DiskLoeschen	2		/* Löschen Button				*/
#define GD_Zahlart		3		/* Zahlart MX-Button			*/
#define GD_Drucken		4		/* Drucken Button				*/
#define GD_Abbrechen		5		/* Abbrechen Button			*/
#define GD_AName			6		/* Absender: Name				*/
#define GD_AStrasse		7		/* Absender: Strasse			*/
#define GD_AOrt			8		/* Absender: Ort				*/
#define GD_KundNr			9		/* Kundennummer				*/
#define GD_EName			10		/* Empfänger: Name			*/
#define GD_EStrasse		11		/* Empfänger: Strasse		*/
#define GD_EOrt			12		/* Empfänger: Ort				*/
#define GD_DiskAender	13		/* Disk ändern					*/
#define GD_Abstand		14		/* Abstand zum Druckbeginn	*/

/* Anzahl der Gadgets definieren (0 bis 14 = 15)			*/
#define Bestellen_CNT									15

/* Die Nummern der Menus mit Konkreten Bezeichnungen		*/
#define MENU_FOO_SPE		1		/* Speichern					*/
#define MENU_FOO_DRU		2		/* Drucken						*/
#define MENU_FOO_INF		3		/* Information					*/
#define MENU_FOO_END		4		/* Ende							*/	
#define MENU_FOO_SSP		5		/* Speichern als ...			*/

/* Screenstruktur löschen											*/
struct Screen         *Scr = NULL;
/* Public Screen Name löschen										*/
UBYTE                 *PubScreenName = NULL;
/* DrawInfo deklarieren und löschen								*/
struct DrawInfo		 *dri = NULL;
/* VisualInfo löschen												*/
APTR                   VisualInfo = NULL;
/* Window Struktur löschen											*/
struct Window         *BestellenWnd = NULL;
/* Gadget Struktur löschen											*/
struct Gadget         *BestellenGList = NULL;
/* Menu Struktur löschen											*/
struct Menu           *BestellenMenus = NULL;
/* Anzahl GadgetStrukturen festlegen (15)						*/
struct Gadget         *BestellenGadgets[15];
/* Breite des Fensters (wird nach Fontbreite umgerechnet)*/
UWORD                  BestellenWidth = 460;
/* Höhe des Fenster (wird nach Fonthöhe umgerechnet)		*/
UWORD                  BestellenHeight = 250;
/* Name des Fensters festlegen									*/
UBYTE                 *BestellenWdt = (UBYTE *)"Time.guide Bestellprogramm";
/* Struktur Textatribute mit Fontinformationen definieren*/
struct TextAttr       *Font, Attr;
/* Definiere Felder für die Fontbreite und Höhe				*/
UWORD                  FontX, FontY;
/* Definiere Felder für den minimalabstand des Fensters	*/
UWORD                  OffX, OffY;
/* Textatribrute für das Fenster									*/
struct TextFont       *BestellenFont = NULL;

/* Texte für das Zahlungsform-MX-Gadget						*/
UBYTE *Gadget300Labels[] = {
	(UBYTE *)"Na_chnahme",
	(UBYTE *)"_Vorkasse",
	(UBYTE *)"_Rechnung",
	NULL };

/* Zusätzliche Texte und deren Position						*/
struct IntuiText BestellenIText[] = {
	1, 0, JAM1,45, 14, NULL, (UBYTE *)"Absender:", NULL,
	1, 0, JAM1,45, 132, NULL, (UBYTE *)"Empfänger:", NULL };

/* Anzahl zusätzlicher Texte										*/
#define Bestellen_TNUM 2

/* Bereitet die Menu-Nummern auf									*/
#define V(x) ((void *)x)

/* MenuStruktur füllen												*/
struct NewMenu BestellenNewMenu[] = {
	NM_TITLE, (STRPTR)"Projekt",					NULL,				0, NULL, NULL,
	 NM_ITEM, (STRPTR)"Speichern",				(STRPTR)"S",	0, 0L, V(MENU_FOO_SPE),
	 NM_ITEM, (STRPTR)"Speichern als ...",		(STRPTR)"A",	0, 0L, V(MENU_FOO_SSP),
	 NM_ITEM, (STRPTR)"Drucken",					(STRPTR)"P",	0, 0L, V(MENU_FOO_DRU),
	 NM_ITEM, (STRPTR)NM_BARLABEL,				NULL,				0, 0L, NULL,
	 NM_ITEM, (STRPTR)"Über T_Bestellen...",	(STRPTR)"I",	0, 0L, V(MENU_FOO_INF),
	 NM_ITEM, (STRPTR)NM_BARLABEL, 				NULL,				0, 0L, NULL,
	 NM_ITEM, (STRPTR)"Beenden",					(STRPTR)"Q",	0, 0L, V(MENU_FOO_END),
	  NM_END, NULL,									NULL,				0, 0L, NULL
};

/* Gadgettypen definieren											*/
UWORD BestellenGTypes[] = {
	LISTVIEW_KIND,
	BUTTON_KIND,
	BUTTON_KIND,
	MX_KIND,
	BUTTON_KIND,
	BUTTON_KIND,
	STRING_KIND,
	STRING_KIND,
	STRING_KIND,
	STRING_KIND,
	STRING_KIND,
	STRING_KIND,
	STRING_KIND,
	STRING_KIND,
	INTEGER_KIND
};

/* Gadgets festlegen													*/
struct NewGadget BestellenNGad[] = {
	242, 24, 115, 156, (UBYTE *)"T_ime-Disks:", NULL, GD_Diskliste, PLACETEXT_ABOVE, NULL, NULL,
	242, 195, 47, 20, (UBYTE *)"N_eu", NULL, GD_NeueDisk, PLACETEXT_IN, NULL, NULL,
	289, 195, 68, 20, (UBYTE *)"Lösc_hen", NULL, GD_DiskLoeschen, PLACETEXT_IN, NULL, NULL,
	361, 52, 17, 9, NULL, NULL, GD_Zahlart, PLACETEXT_RIGHT, NULL, NULL,
	4, 225, 88, 20, (UBYTE *)"_Drucken", NULL, GD_Drucken, PLACETEXT_IN, NULL, NULL,
	366, 225, 88, 20, (UBYTE *)"_Abbrechen", NULL, GD_Abbrechen, PLACETEXT_IN, NULL, NULL,
	71, 28, 161, 20, (UBYTE *)"_Name", NULL, GD_AName, PLACETEXT_LEFT, NULL, NULL,
	71, 50, 161, 20, (UBYTE *)"_Straße", NULL, GD_AStrasse, PLACETEXT_LEFT, NULL, NULL,
	71, 72, 161, 20, (UBYTE *)"PLZ/_Ort", NULL, GD_AOrt, PLACETEXT_LEFT, NULL, NULL,
	71, 94, 161, 20, (UBYTE *)"_KundNr", NULL, GD_KundNr, PLACETEXT_LEFT, NULL, NULL,
	71, 147, 161, 20, (UBYTE *)"Na_me", NULL, GD_EName, PLACETEXT_LEFT, NULL, NULL,
	71, 169, 161, 20, (UBYTE *)"S_traße", NULL, GD_EStrasse, PLACETEXT_LEFT, NULL, NULL,
	71, 191, 161, 20, (UBYTE *)"_PLZ/Ort", NULL, GD_EOrt, PLACETEXT_LEFT, NULL, NULL,
	242, 174, 115, 20, NULL, NULL, GD_DiskAender, 0, NULL, NULL,
	361, 24, 86, 20, (UBYTE *)"_Leerzeil.", NULL, GD_Abstand, PLACETEXT_ABOVE, NULL, NULL
};

/* Tags zu den Gadgets												*/
ULONG BestellenGTags[] = {
	(GTLV_ShowSelected), NULL, (GT_Underscore), '_', (TAG_DONE),
	(GT_Underscore), '_', (TAG_DONE),
	(GT_Underscore), '_', (TAG_DONE),
	(GTMX_Labels), (ULONG)&Gadget300Labels[ 0 ], (GT_Underscore), '_', (TAG_DONE),
	(GT_Underscore), '_', (TAG_DONE),
	(GT_Underscore), '_', (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 29, (GT_Underscore), '_', (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 29, (GT_Underscore), '_', (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 29, (GT_Underscore), '_', (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 29, (GT_Underscore), '_', (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 29, (GT_Underscore), '_', (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 29, (GT_Underscore), '_', (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 29, (GT_Underscore), '_', (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTST_MaxChars), 14, (TAG_DONE),
	(STRINGA_ExitHelp), TRUE, (GTIN_Number), 0, (GTIN_MaxChars), 3, (GT_Underscore), '_', (TAG_DONE)
};

/* Vordefinieren sämtlicher im Programm vorkommender		*/
/* Unterprogramme														*/
/* eine der Tasten die nix aufm Bildschirm hinterlassen	*/
void Abfrage_Rawkey( UWORD code, struct Gadget *gd);

/* Positionen nach Fontbreite umrechnen						*/
static UWORD ComputeX( UWORD value );

/* Positionen nach Fonthöhe umrechnen							*/
static UWORD ComputeY( UWORD value );

/* Computerbreite und -höhe Bestimmen							*/
static void ComputeFont( UWORD width, UWORD height );

/* Voreinstellungen fürs Fenster (Screen vorbereiten)		*/
int SetupScreen( void );

/* Sreen wieder zurücksetzen										*/
void CloseDownScreen( void );

/* Texte und BevelBoxes aufs Fenster zeichnen				*/
void BestellenRender( void );

/* Fenster öffenen													*/
int OpenBestellenWindow( void );

/* Fenster wieder dicht machen									*/
void CloseBestellenWindow( void );

/*	Gadtools-Gadget einschalten 									*/
void gt_OnGadget( struct Gadget 	*gad, struct Window		*w );

/*	...und wieder aus...												*/
void gt_OffGadget( struct Gadget 	*gad, struct Window	*w );

/*  String-Gadgets mit nem string füllen						*/
void gt_SetString( struct Gadget	*gad,
				   struct Window	*w,
				   char				*string );

/* und nachschaun, welcher drinnen steckt						*/
char * gt_GetString( struct Gadget	*gad );

/* Integer-Gadgets mit ner Zahl füllen							*/
void gt_SetInteger( struct Gadget	*gad,
				    struct Window	*w,
				    LONG			value );

/* und nachschaun, welche drinnen steckt						*/
LONG gt_GetInteger( struct Gadget	*gad );

/* Liste anhängen														*/
void gt_AttachList(	struct Gadget 	*lv,
					struct Window 	*w,
				 	struct List 	*list );

/* Aktuellen Eintrag setzen										*/
void gt_SetLV( struct Gadget	*gad,
			   struct Window	*w,
			   ULONG			value);

/* x-ten Eintrag aus einer Exec-Liste holen */
struct Node * gt_GetListEntry( struct List *l,
							   int num );

/* Nummer einer Node aus einer Liste feststellen			*/
int gt_GetListEntryNum(	struct List *l,
						struct Node *n );

/* Anzahl Einträge einer Liste zählen							*/
int gt_GetListNumEntries( struct List *l );

/* Gadgets ein oder Ausschalten									*/
void checkonoff( void );

/* Neuer Eintrag in die Liste	aufnehmen						*/
void newvdb( void );

/* Libraries öffnen													*/
BOOL OpenAll();

/* Libraries schließen												*/
void CloseAll();

/* Unterprogramm zum Einlesen der Einstellungen				*/
void EinstLesen();

/* Unterprogramm zum Schreiben der Einstellungen			*/
void EinstSchreiben();

/* Sortiert einen neuen Eintrag in die Liste ein.			*/
long NeuerEintrag(char *Eintrag);

/* Einen Eintrag aus der Liste entfernen						*/
void EintragLoeschen();

/* Unterprogramm zum Einlesen der Time-Diskettendaten		*/
void DatenLesen();

/* Unterprogramm zum Schreiben der Time-Diskettendaten	*/
void DatenSchreiben();

/* Die Bestellung auf eine Postkarte Drucken					*/
void Drucken( struct List *l, char dat[] );

/* Window mit den Voreingestellten Daten füllen				*/
void Winfuell();

/* Wenn jemand versucht ein Gadget zu erdrücken				*/
BOOL Abfrage_Gadgetup( struct Gadget *gad, long code);

/* Jemand hat das Menu benutzt									*/
BOOL Abfrage_Menuepick( UWORD code);

/* Eine handelsübliche Taste wurde gedrückt					*/
BOOL Abfrage_Vanillakey(UWORD code);

/* eine der Tasten die nix aufm Bildschirm hinterlassen	*/
void Abfrage_Rawkey( UWORD code, struct Gadget *gd);

/* eine der Tasten die nix aufm Bildschirm hinterlassen	*/
void Abfrage_Menuhelp( UWORD code);


/* Positionen nach Fontbreite umrechnen						*/
static UWORD ComputeX( UWORD value )
{
	return(( UWORD )((( FontX * value ) + 3 ) / (UWORD)7 ));
}

/* Positionen nach Fonthöhe umrechnen							*/
static UWORD ComputeY( UWORD value )
{
	return(( UWORD )((( FontY * value ) + 6 ) / (UWORD)12 ));
}

/* Computerbreite und -höhe Bestimmen							*/
static void ComputeFont( UWORD width, UWORD height )
{
	/* Voreingestellten Font benutzen							*/
	Font = &Attr;
	/* Fontname bestimmen											*/
	Font->ta_Name = (STRPTR)Scr->RastPort.Font->tf_Message.mn_Node.ln_Name;
	/* Fonthöhe bestimmen											*/
	Font->ta_YSize = FontY = Scr->RastPort.Font->tf_YSize;
	/* Fontbreite bestimmen											*/
	FontX = Scr->RastPort.Font->tf_XSize;

	/* minimaler horizontaler Abstand							*/
	OffX = Scr->WBorLeft;
	/* minimaler vertikaler Abstand								*/
	OffY = Scr->RastPort.TxHeight + Scr->WBorTop + 1;

	/* Überprüfen, ob das Fenster nicht zu groß wird		*/ 
	if ( width && height ) {
		/* Wenn es horizontal zu groß wird, oder				*/
		if (( ComputeX( width ) + OffX + Scr->WBorRight ) > Scr->Width )
			goto UseTopaz;
		/* vertikal, dann benutze den Topas 8 Font			*/
		if (( ComputeY( height ) + OffY + Scr->WBorBottom ) > Scr->Height )
			goto UseTopaz;
	}
	return;

/* Topas Font verwenden, weils Fenster sonst zu groß wird*/
UseTopaz:
	Font->ta_Name = (STRPTR)"topaz.font";
	FontX = FontY = Font->ta_YSize = 8;
}

/* Voreinstellungen fürs Fenster (Screen vorbereiten)		*/
int SetupScreen( void )
{
	/* Schaun, ob wir nen PubScreen verwenden können		*/
	if ( ! ( Scr = LockPubScreen( PubScreenName )))
		return( 1L );

	/* Schrifthöhe und -breit bestimmen							*/
	ComputeFont( 0, 0 );

	/* Visualinfo setzen (Zeiger, wo es sichtbar wird)		*/
	if ( ! ( VisualInfo = GetVisualInfo( Scr, TAG_DONE )))
		return( 2L );

	/* wenn alles glatt gegangen ist, 0 zurückgeben			*/
	return( 0L );
}

/* Sreen wieder zurücksetzen										*/
void CloseDownScreen( void )
{
	/* falls wir ein VisualInfo gekriegt haben, freigeben	*/
	if ( VisualInfo ) {
		FreeVisualInfo( VisualInfo );
		VisualInfo = NULL;
	}

	/* PubScreen wieder zurücksetzen								*/
	if ( Scr        ) {
		UnlockPubScreen( NULL, Scr );
		Scr = NULL;
	}
}

/* Texte und BevelBoxes aufs Fenster zeichnen				*/
void BestellenRender( void )
{
	struct IntuiText	it;
	UWORD			cnt;

	/* Font berechnen													*/
	ComputeFont( BestellenWidth, BestellenHeight );

	/* Absenderumrandende BevelBox zeichnen					*/
	DrawBevelBox( BestellenWnd->RPort, OffX + ComputeX( 10 ),
					OffY + ComputeY( 24 ),
					ComputeX( 227 ),
					ComputeY( 94 ),
					GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE );
	/* Empfängerumrandende BevelBox zeichnen					*/
	DrawBevelBox( BestellenWnd->RPort, OffX + ComputeX( 10 ),
					OffY + ComputeY( 143 ),
					ComputeX( 227 ),
					ComputeY( 72 ),
					GT_VisualInfo, VisualInfo, GTBB_Recessed, TRUE, TAG_DONE );
		/* Allumrandende BevelBox zeichnen							*/
	DrawBevelBox( BestellenWnd->RPort, OffX + ComputeX( 2 ),
					OffY + ComputeY( 3 ),
					ComputeX( 453 ),
					ComputeY( 218 ),
					GT_VisualInfo, VisualInfo, TAG_DONE );

	/* Texte ausgeben													*/
	for ( cnt = 0; cnt < Bestellen_TNUM; cnt++ ) {
		/* Text aufbereiten											*/
		CopyMem(( char * )&BestellenIText[ cnt ], ( char * )&it, (long)sizeof( struct IntuiText ));
		/* Font festlegen												*/
		it.ITextFont = Font;
		/* horizontale Position festlegen						*/
		it.LeftEdge  = OffX + ComputeX( it.LeftEdge ) - ( IntuiTextLength( &it ) >> 1 );
		/* vertikale Position festlegen							*/
		it.TopEdge   = OffY + ComputeY( it.TopEdge ) - ( Font->ta_YSize >> 1 );
		/* Text ausgeben												*/
		PrintIText( BestellenWnd->RPort, &it, 0, 0 );
	}
}

/* Fenster öffenen													*/
int OpenBestellenWindow( void )
{
	/* NewGadget Struktur konkret anlegen						*/
	struct NewGadget	ng;
	/* Gadget Struktur konkret anlegen							*/
	struct Gadget	*g;
	/* Zwei laufvariable definieren								*/
	UWORD		lc, tc;
	/* Für die horizontale und vertikale Größe				*/
	UWORD		ww, wh;

	/* Fontröße berechnen											*/
	ComputeFont( BestellenWidth, BestellenHeight );

	/* absolute Fenstergröße horizontal berechnen			*/
	ww = ComputeX( BestellenWidth );
	/* absolute Fenstergröße vertikal berechnen				*/
	wh = ComputeY( BestellenHeight );

	/* Font öffnen, wenns fehlschlägt, Fehler zurückgeben	*/
	if ( ! ( BestellenFont = OpenDiskFont( Font )))
		return( 5L );

	/* Liste fürs erstellen der Gadgets erstellen			*/
	if ( ! ( g = CreateContext( &BestellenGList )))
		return( 1L );

	/* wiederhole, bis alle Gadgets erstellt sind			*/
	for( lc = 0, tc = 0; lc < Bestellen_CNT; lc++ )
	{
		/* Speicherbereich in dem die Liste definiert ist	*/
		/* an die Liste ranhängen									*/
		CopyMem((char * )&BestellenNGad[ lc ], (char * )&ng, (long)sizeof( struct NewGadget ));

		/* VisualInfo an die Gadgetstructru übergeben		*/
		ng.ng_VisualInfo = VisualInfo;
		/* Font fürs Gadget festlegen								*/
		ng.ng_TextAttr   = Font;
		/* horizontale Position errechnen						*/
		ng.ng_LeftEdge   = OffX + ComputeX( ng.ng_LeftEdge );
		/* vertikale Position errechnen							*/
		ng.ng_TopEdge    = OffY + ComputeY( ng.ng_TopEdge );
		/* Breite berechnen											*/
		ng.ng_Width      = ComputeX( ng.ng_Width );
		/* und die Höhe berechnen									*/
		ng.ng_Height     = ComputeY( ng.ng_Height);

		/* Das ganze können wir jetzt mal herstellen			*/
		BestellenGadgets[ lc ] = g = CreateGadgetA((ULONG)BestellenGTypes[ lc ], g, &ng, ( struct TagItem * )&BestellenGTags[ tc ] );

		/* tc erhöhen													*/
		while( BestellenGTags[ tc ] ) tc += 2;
		tc++;

		/* Bei einem Fehler, brechen wir die Sache ab		*/
		if ( NOT g )
			return( 2L );
	}

	/* Menus noch vorbereiten										*/
	/* Unter OS 3.x 													*/
	if( NOS )
	{
		/* Verwenden wir die Prefs-Menü-Farben					*/
		dri = GetScreenDrawInfo( Scr );
		if ( ! ( BestellenMenus = CreateMenus( BestellenNewMenu, GTMN_FrontPen, dri->dri_Pens[BARDETAILPEN], GTMN_NewLookMenus, TRUE, TAG_DONE )))
			return( 3L );
	}
	/* unter OS 2.x													*/
	else
	{
		/* können wir standardmäßig die Farbe 0 verwenden	*/
		if ( ! ( BestellenMenus = CreateMenus( BestellenNewMenu, GTMN_FrontPen, 0L, TAG_DONE )))
			return( 3L );
	}

	/* und herstellen													*/
	LayoutMenus( BestellenMenus, VisualInfo, TAG_DONE );

	/* Schon können wir es wagen, das Fenster zu öffnen	*/
	if ( ! ( BestellenWnd = OpenWindowTags( NULL,
				WA_Left,				(Scr->Width  - (ww + OffX + Scr->WBorRight )) / (UWORD)2,
				WA_Top,				(Scr->Height - (wh + OffY + Scr->WBorBottom)) / (UWORD)2,
				WA_Width,			ww + OffX + Scr->WBorRight,
				WA_Height,			wh + OffY + Scr->WBorBottom,
				WA_IDCMP,			IDCMP_CLOSEWINDOW|IDCMP_GADGETUP|IDCMP_GADGETDOWN|IDCMP_MENUHELP|IDCMP_MENUPICK|IDCMP_VANILLAKEY|IDCMP_GADGETHELP|IDCMP_RAWKEY,
				WA_Flags,			WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE|WFLG_NEWLOOKMENUS,
				WA_Gadgets,			BestellenGList,
				WA_Title,			BestellenWdt,
				WA_ScreenTitle,	"Bestellprogramm zur Time.guide ©1994-95 MT Graphic & Design",
				WA_PubScreen,		Scr,
				WA_MenuHelp,		TRUE,
				WA_NewLookMenus,	TRUE,
				TAG_DONE )))
	return( 4L );

	/* Hängen wir das Menu noch dran								*/
	SetMenuStrip( BestellenWnd, BestellenMenus );
	/* Kurzer refresh, sonst schmiert uns das Ding ab		*/
	GT_RefreshWindow( BestellenWnd, NULL );

	/* Die Bevel Boxen und ein wenig Text draufzeichnen	*/
	BestellenRender();

	/* Alles Klar Boss												*/
	return( 0L );
}

/* Fenster wieder dicht machen									*/
void CloseBestellenWindow( void )
{
	/* Hat das mit den Menus hingehaun?							*/
	if ( BestellenMenus      )
	{
		/* Vom Fenster abmontieren									*/
		ClearMenuStrip( BestellenWnd );
		/* und freigeben												*/
		FreeMenus( BestellenMenus );
		/* Vermerken, daß alles gelöscht wurde					*/
		BestellenMenus = NULL;
	}

	/* Konnte das Fenster geöffnet werden						*/
	if ( BestellenWnd        )
	{
		/* dann machen wir es wieder zu (wird kalt drausen)*/
		CloseWindow( BestellenWnd );
		/* und vermerken das mal eben								*/
		BestellenWnd = NULL;
	}

	/* Konnten die Gadgets erzeugt werden						*/
	if ( BestellenGList      )
	{
		/* Befreien wir sie wieder									*/
		FreeGadgets( BestellenGList );
		/* und vermerken auch dieses								*/
		BestellenGList = NULL;
	}

	/* Na, können Sie es sich denken? Konnte der Font...	*/
	if ( BestellenFont )
	{
		/* Dann schließen wir auch diesen						*/
		CloseFont( BestellenFont );
		/* und schreibens uns hinter die Löffel				*/
		BestellenFont = NULL;
	}
}

/*	Gadtools-Gadget einschalten 									*/
void gt_OnGadget( struct Gadget 	*gad,
				  struct Window		*w )
{
	GT_SetGadgetAttrs( gad, w, NULL, GA_DISABLED, FALSE, TAG_DONE );
}

/*	...und wieder aus...												*/
void gt_OffGadget( struct Gadget 	*gad,
				   struct Window	*w )
{
	GT_SetGadgetAttrs( gad, w, NULL, GA_DISABLED, TRUE, TAG_DONE );
}

/*  String-Gadgets mit nem string füllen						*/
void gt_SetString( struct Gadget	*gad,
				   struct Window	*w,
				   char				*string )
{
	GT_SetGadgetAttrs( gad, w, NULL, GTST_String, string, TAG_DONE );
}

/* und nachschaun, welcher drinnen steckt						*/
char * gt_GetString( struct Gadget	*gad )
{
	struct StringInfo *si = gad->SpecialInfo;

	if( si )
		return( ( char * ) si->Buffer );
	else
		return( NULL );
}

/* Integer-Gadgets mit ner Zahl füllen							*/
void gt_SetInteger( struct Gadget	*gad,
				    struct Window	*w,
				    LONG			value )
{
	GT_SetGadgetAttrs( gad, w, NULL, GTIN_Number, value, TAG_DONE );
}

/* und nachschaun, welche drinnen steckt						*/
LONG gt_GetInteger( struct Gadget	*gad )
{
	struct StringInfo *si = gad->SpecialInfo;

	if( si )
		return( si->LongInt );
	else
		return( NULL );

}

/* Listenverwaltung für Listview-Gadgets						*/

/* Liste anhängen
 * "list" kann ~0 (-1) sein, dann ist kein Listenzugriff möglich
 */

void gt_AttachList(	struct Gadget 	*lv,
					struct Window 	*w,
				 	struct List 	*list )
{
	GT_SetGadgetAttrs( lv, w, NULL, GTLV_Labels, list, TAG_DONE );
}

/* Aktuellen Eintrag setzen
 * incl. Automatischem Positionieren, wenn der Eintrag außerhalb
 * des sichtbaren Bereichs ist (maximal 12 Einträge darstellbar)
 */
void gt_SetLV( struct Gadget	*gad,
			   struct Window	*w,
			   ULONG			value)
{
	ULONG i;
	/* sollte ein Eintrag ausgewählt sein,						*/
	if( value >= 0 )
	{
		/* schau nach, welcher ganz oben in der Liste steht*/
		GT_GetGadgetAttrs( gad, w, NULL, GTLV_Top, &i, TAG_DONE );
		/* ist er größer als der gewählte,						*/
		if(value < i)
		{
			/* dann rutschen wir ein wenig hoch in der Liste*/
			i = value;
			GT_SetGadgetAttrs( gad, w, NULL, GTLV_Top, i, TAG_DONE );
		}
		/* sollte er zu hoch sein,									*/
		else if(value - i > 10)
		{
			/* müssen wir die Liste ein wenig runterblätten	*/
			i = value - 11;
			GT_SetGadgetAttrs( gad, w, NULL, GTLV_Top, i, TAG_DONE );
		}
	}
	/* Nun können der Eintrag ausgewählt werden.				*/
	GT_SetGadgetAttrs( gad, w, NULL, GTLV_Selected, value, TAG_DONE );
}

/* x-ten Eintrag aus einer Exec-Liste holen */
struct Node * gt_GetListEntry( struct List *l,
							   int num )
{
	int count = 0;
	struct Node *n = l->lh_Head;

	while( n->ln_Succ )
	{
		if( num==count ) return( n );
		n = n->ln_Succ;
		count++;
	}
	return( NULL );
}

/* Nummer einer Node aus einer Liste feststellen
 * -1 falls nicht in Liste
 */
int gt_GetListEntryNum(	struct List *l,
						struct Node *n )
{
	int count = 0;
	struct Node *r = l->lh_Head;

	while( r->ln_Succ )
	{
		if( r==n ) return( count );
		r = r->ln_Succ;
		count++;
	}
	return( -1 );
}

/* Anzahl Einträge einer Liste zählen							*/
int gt_GetListNumEntries( struct List *l )
{
	int count = 0;
	struct Node *n = l->lh_Head;

	while( n->ln_Succ )
	{
		n = n->ln_Succ;
		count++;
	}

	return( count );
}

/* Gadgets ein oder Ausschalten									*/
void checkonoff( void )
{
	/* Wenn ein Eintrag aus der Liste angewählt ist,		*/
	if( currentvdb ) 
	{
		/* schalte die Gadgets ein									*/
		gt_OnGadget( BestellenGadgets[ GD_DiskLoeschen ], BestellenWnd );
		gt_OnGadget( BestellenGadgets[ GD_DiskAender ], BestellenWnd );
	}
	else
	{
		/* ansonsten brauchen wir sie gerade mal nicht		*/
		gt_OffGadget( BestellenGadgets[ GD_DiskLoeschen ], BestellenWnd );
		gt_OffGadget( BestellenGadgets[ GD_DiskAender ], BestellenWnd );
	}
}

/* Neuer Eintrag in die Liste	aufnehmen						*/
void newvdb( void )
{
	/* Neue Sturktur anlegen										*/
	struct VDBnode *new;

	/* Speicher dafür reservieren									*/
	new = AllocVec( sizeof( *new ), MEMF_CLEAR );

	/* Nur weitermachen, wenn es geklappt hat					*/
	if( !new )
		return;

	/* den neuen Satz zum aktuellen machen						*/
	currentvdb = new;
	new->n.ln_Name = new->d.Name;

	/* der neue Satz lautet vorrübergehend "- Neu -"		*/
	strcpy( new->d.Name, "- Neu -" );

	/* Liste abhängen													*/
	gt_AttachList( BestellenGadgets[GD_Diskliste], BestellenWnd, (struct List *) ~0 );

	/* Priorität = ASCII-Wert des ersten Buchstaben			*/
	new->n.ln_Pri	 = - new->d.Name[0];

	/* an die Liste nach Prioritäten sortiert anhängen		*/	
	Enqueue( &vdblist, (struct Node *) new );

	/* geänderte Liste wieder anhängen							*/
	gt_AttachList( BestellenGadgets[GD_Diskliste], BestellenWnd, &vdblist );

	/* im ListviewGadget aktivieren								*/
	gt_SetLV(BestellenGadgets[GD_Diskliste], BestellenWnd, gt_GetListEntryNum(&vdblist, (struct Node *) new));

	/* Wenn die Gadgets abgeschaltet sind, einschalten		*/
	checkonoff();

	/* den "- Neu -" ins String Gadget schreiben und zur	*/
	gt_SetString( BestellenGadgets[GD_DiskAender], BestellenWnd, currentvdb->d.Name );

	/* Änderung aktivieren, oder wollen Sie eine Test Disk*/
	ActivateGadget( BestellenGadgets[GD_DiskAender], BestellenWnd, NULL );
}

/* Libraries öffnen													*/
BOOL OpenAll()
{
	/* Kick 2.0 muß vorhanden sein
	 * Libraryversionen mind. 37
	 */

	/* Intuition.library in der 39er Version öffnen (3.x)	*/
	IntuitionBase=(struct IntuitionBase *)
	    OpenLibrary("intuition.library",39L);
	/* Wenn das geklappt hat										*/
	if( IntuitionBase != NULL)
	{
		NOS = TRUE;
	}
	/* Steht jedoch kein OS 3.x zur Verfügung					*/
	else
	{
		/* müssen wir mit der 2.x Version auskommen			*/	
		IntuitionBase=(struct IntuitionBase *)
		    OpenLibrary("intuition.library",37L);
	}

	/* Graphics.library öffnen										*/
	GfxBase=(struct GfxBase *)
	    OpenLibrary("graphics.library",37L);

	/* GadTools.library öffnen										*/
   GadToolsBase=(struct Library *)
       OpenLibrary("gadtools.library",37L);

	/* Asl.library öffnen (nicht zwindend notwendig)		*/
	AslBase       = OpenLibrary("asl.library", 37L);

	/* AmigaGuide.library (nicht zwingend notwendig)		*/
	AmigaGuideBase = OpenLibrary("amigaguide.library", 0L);


	/* Hat es nicht geklappt, Fehler zurückgeben				*/
	if(GadToolsBase	== NULL ||
		GfxBase			== NULL ||
		IntuitionBase	== NULL)
		return FALSE;
	return TRUE;
}

/* Libraries schließen												*/
void CloseAll()
{
	/* AmigaGuide.library schließen, wenn sie offen ist	*/
	if( AmigaGuideBase != NULL )
		CloseLibrary( ( struct Library *)AmigaGuideBase );
	/* Asl.library schließen, wenn sie offen ist				*/
	if( AslBase != NULL)
		CloseLibrary( ( struct Library *)AslBase );
	/* GadTools.library schließen, wenn sie offen ist		*/
	if( GadToolsBase != NULL)
		CloseLibrary( ( struct Library *)GadToolsBase );
	/* Graphics.library schließen, wenn sie offen ist		*/
	if( GfxBase != NULL)
		CloseLibrary( ( struct Library *)GfxBase );
	/* Intuition.library schließen, wenn sie offen ist		*/
	if( IntuitionBase != NULL)
		CloseLibrary( ( struct Library *)IntuitionBase );
	return;
}

/* Unterprogramm zum Einlesen der Einstellungen				*/
void EinstLesen()
{
	/* Datei öffnen													*/
	BPTR is;
	is = Open(Einst_File,MODE_OLDFILE);
	/* Wenn das geklappt hat,										*/
	if(is)
	{
		/* lies die Einstellungen									*/
		Read(is, &P1, sizeof( P1 ));
		/* Schließ die Datei wieder								*/
		Close(is);
	}
}

/* Unterprogramm zum Schreiben der Einstellungen			*/
void EinstSchreiben()
{
	/* Datei öffnen													*/
	BPTR os;
	os = Open(Einst_File, MODE_NEWFILE);
	/* Wenn das geklappt hat,										*/
	if(os)
	{
		/* schreib die Einstellungen								*/
		Write(os, &P1, sizeof( P1 ));
		/* Schließ die Datei wieder								*/
		Close(os);
	}
}

/* Sortiert einen neuen Eintrag in die Liste ein.			*/
long NeuerEintrag(char *Eintrag)
{
	long Entries = 0;
	long i = 0;
	struct VDBnode *n;
	struct VDBnode *m;

	/* Anzahl der bereits existierenden Eintragungen		*/
	Entries = gt_GetListNumEntries( &vdblist );

	/* Schleife vom Ende bis zum Anfang der Liste			*/
	for( i = Entries-1; i >= 0; i--) 
	{
		/* Eintrag aus der Liste Holen							*/
		m = (struct VDBnode *) gt_GetListEntry( &vdblist, i );

		/* Der Eintrag ist bereits vorhanden -> ignorieren	*/
		if(strcmp(m->d.Name, Eintrag)==0)
			return i;

		/* Die richtige Stelle wurde gefunden -> Einfügen	*/
		if(strcmp(m->d.Name, Eintrag)<0)
		{
			/* Speicher alokieren									*/
			n = AllocVec( sizeof( *n ), MEMF_CLEAR );
			if( n )
			{
				/* die ganze Sache aufbereiten					*/
				strcpy(n->d.Name, Eintrag);
				n->n.ln_Name = n->d.Name;
				n->n.ln_Pri  = - n->d.Name[0];
				/* und dahinter anhängen							*/
				Insert( &vdblist, (struct Node *) n, (struct Node *) m );
			}
			/* Eingefügte Pos. = i+1, das geben wir zurück	*/
			return ++i;
		}
	}

	/* Kein kleinerer Eintrag gefunden?							*/
	n = AllocVec( sizeof( *n ), MEMF_CLEAR );
	if( n )
	{
		/* die ganze Sache aufbereiten							*/
		strcpy(n->d.Name, Eintrag);
		n->n.ln_Name = n->d.Name;
		n->n.ln_Pri  = - n->d.Name[0];
		/* dann setz ihn vorne dran								*/
		AddHead( &vdblist, (struct Node *) n );
	}
	/* Eingefügte Position = 0, das geben wir zurück		*/
	return 0;
}

/* Einen Eintrag aus der Liste entfernen						*/
void EintragLoeschen()
{
	long i;
	/* Wenn ein Eintrag ausgewählt ist							*/
	if(currentvdb)
	{
		/* Die Nummer des Eintrags bestimmen					*/
		i = gt_GetListEntryNum(&vdblist, (struct Node *) currentvdb);
		/* Ist diese > 0, wird der nächste Eintrag eins kl.*/
		if(i > 0)
			i--;
		/* Ansonsten 0 (der Beginn der Liste)					*/
		else
			i = 0;
		/* Liste abhängen												*/
		gt_AttachList( BestellenGadgets[ GD_Diskliste ], BestellenWnd, (struct List *) ~0 );
		/* Den Eintrag entfernen									*/
		Remove( (struct Node *) currentvdb );
		/* ebenso den passenden Vektor							*/
		FreeVec( currentvdb );
		/* Liste wieder anhängen									*/
		gt_AttachList( BestellenGadgets[ GD_Diskliste ], BestellenWnd, &vdblist );
		/* Neuer aktueller Eintrag									*/
		currentvdb = (struct VDBnode *) gt_GetListEntry( &vdblist, i );
		/* Wenn keiner mehr drinnen ist, Gad. abschalten	*/
		checkonoff();
		/* Neuen aktuellen Eintag in der Liste auswählen	*/
		gt_SetLV( BestellenGadgets[ GD_Diskliste ], BestellenWnd, i );
		/* und im Feld darunter anzeigen							*/
		gt_SetString( BestellenGadgets[GD_DiskAender], BestellenWnd, currentvdb->d.Name );
	}
}

/* Unterprogramm zum Einlesen der Time-Diskettendaten		*/
void DatenLesen()
{
	FILE *is;
	char lespuf[15];

	/* Liste initialisieren											*/
	NewList( &vdblist );
	/* Bei Beginn noch keinen aktuellen Eintrag				*/
	currentvdb = NULL;

	/* Datei öffnen zum lesen (read -> "r")					*/
	is = fopen("T:Time_Remember.dat", "r");
	if(is)
	{
		/* Solange was in der Datei steckt, lesen				*/
		while(fgets(lespuf, 14, is))
		{
			/* und an die Liste dranhängen						*/
			NeuerEintrag(lespuf);
		}
		/* Hinterher die Datei wieder dicht machen			*/
		fclose(is);
	}
}

/* Unterprogramm zum Schreiben der Time-Diskettendaten	*/
void DatenSchreiben()
{
	struct VDBnode *n;
	FILE *os;

	/* Datei zum Schreiben öffnen (write -> "w")				*/
	os = fopen("T:Time_Remember.dat", "w");
	/* Die Liste von Anfang bis Schluß durchackern			*/
	while( ( n = (struct VDBnode *) RemHead( &vdblist ) ) )
	{
		/* Hat das öffnen hingehauen								*/
		if(os)
			{
				/* Disknamen reinschreiben							*/
				fputs( n->d.Name, os );
				fputc( '\n', os);
			}
		/* Vektor freigeben, den brachen wir nichtmehr		*/
		FreeVec(n);
	}
	/* Wenns öffnen geklappt hat, dann Datei schließen		*/
	if(os)
		fclose(os);
}

/* Die Bestellung auf eine Postkarte Drucken					*/
void Drucken( struct List *l, char dat[] )
{
	/* Einen Schreibpuffer für die aufbereitun der Zeilen	*/
	char Schreibpuf[1000];
	char Zeilenpuf[60];
	char i;
	int Druck;
	struct VDBnode *a;
	struct Node *n = l->lh_Head;

	FILE *os;
	/* Requester vorbereiten										*/
	es.es_StructSize	= sizeof(struct EasyStruct);
	es.es_Flags			= 0;

	/* Datei zum drucken oder speichern öffnen				*/
	Druck = !(strcmp("PRT:", dat));
	strcpy(Schreibpuf, dat);
	if (!Druck)
		strcat(Schreibpuf, "_1");
	os = fopen(Schreibpuf, "w");
	/* Hats geklappt?													*/
	if(os)
	{
		/* Wenn gedruckt werden soll,								*/
		if(Druck)
		{
			/* Requester zur Aufford. die Postkarte einzul.	*/
			es.es_Title			= "Kleine Auswahl";
			es.es_TextFormat	= "Bitte Postkart mit der\n      Adresseite\n nach oben einlegen.";
			es.es_GadgetFormat= "Drucken|Abbrechen";

			/* Wenn er mit Drucken bestätigt wurde	i > 0		*/
			i = EasyRequest(BestellenWnd, &es, NULL);
		}
		/* beim Speichern keine Nachfrage						*/
		else
		{
			i = 1;
		}
		/* Falls i > 0 drucken/speichern							*/
		if(i)
		{
			strcpy(Schreibpuf, '\0');
			/* Die Leerzeilen zu Beginn einfügen				*/
			for( i = 0; i < P1.Abstand; i++)
			{
				strcat(Schreibpuf, "\n")
			}
			/* Die Zeile mit dem Absendernamen drucken und	*/
			strcat(Schreibpuf, "  ");
			strcat(Schreibpuf, P1.AName);
			strcat(Schreibpuf, "\n\n");
			/* Die Zeile mit der Kundennummer drucken und	*/
			strcat(Schreibpuf, "  KundenNr: ");
			strcat(Schreibpuf, P1.KundNr);
			strcat(Schreibpuf, "\n\n");
			/* Die Zeile mit der Absenderstraße drucken und	*/
			strcat(Schreibpuf, "  ");
			strcat(Schreibpuf, P1.AStrasse);
			strcat(Schreibpuf, "\n\n");
			/* Die Zeile mit dem Absenderort drucken und		*/
			strcat(Schreibpuf, "  ");
			strcat(Schreibpuf, P1.AOrt);
			strcat(Schreibpuf, "\n\n");
			/* Die Zeile mit dem Empfängernamen drucken und	*/
			strcat(Schreibpuf, "                             ");
			strcat(Schreibpuf, P1.EName);
			strcat(Schreibpuf, "\n\n\n\n");
			/* Die Zeile mit der Empf.straße drucken und		*/
			strcat(Schreibpuf, "                             ");
			strcat(Schreibpuf, P1.EStrasse);
			strcat(Schreibpuf, "\n\n\n\n");
			/* zuguterletzt den Empfängerort drucken und		*/
			strcat(Schreibpuf, "                             ");
			strcat(Schreibpuf, P1.EOrt);
			strcat(Schreibpuf, "\f");
			if (fputs( Schreibpuf, os ) == DOSTRUE)
			{
				/* Schreiben klappte nicht							*/
				es.es_Title			= "Problem!";
				es.es_TextFormat	= "Fehler beim Drucken/Speichern aufgetreten!";
				es.es_GadgetFormat= "Abbrechen";

				EasyRequest(BestellenWnd, &es, NULL);
				os = NULL;
			}
		}
		/* und schließe die Datei wieder							*/
		fclose(os);
	}

	/* Datei zum drucken oder speichern öffnen				*/
	strcpy(Schreibpuf, dat);
	if (!Druck)
		strcat(Schreibpuf, "_2");
	os = fopen(Schreibpuf, "w");
	/* Hats geklappt?													*/
	if(os)
	{
		/* Wenn gedruckt werden soll,								*/
		if(Druck)
		{
			/* Die Aufforderung, die Postkarte umzudrehen	*/
			es.es_TextFormat	= "Bitte Postkart mit der\n     leeren Seite\n nach oben einlegen.";

			/* Wenn er mit Drucken bestätigt wurde				*/
			i = EasyRequest(BestellenWnd, &es, NULL);
		}
		/* beim Speichern keine Nachfrage						*/
		else
			i = 1;
		/* Wenn i > 0													*/
		if(i)
		{
			strcpy(Schreibpuf, '\0');
			/* Die Leerzeilen zu Beginn einfügen				*/
			for( i = 0; i < P1.Abstand; i++)
			{
				strcat(Schreibpuf, "\n")
			}
			/* Ein Text, der klar macht, was wir wollen		*/
			strcat(Schreibpuf, "  Bitte Senden Sie mir folgende Disketten\n");
			/* Nachschaun, welche Zahlungsart aktuell ist	*/
			switch( P1.Versart )
			{
				/* Nachnahme,											*/
				case 0:
					strcat(Schreibpuf, "  per Nachnahme:\n\n");
					break;
				/* Vorkasse oder										*/
				case 1:
					strcat(Schreibpuf, "  per Vorkasse:\n\n");
					break;
				/* gegen Rechnung										*/
				default:
					strcat(Schreibpuf, "  gegen Rechnung:\n\n");
					break;
			}
			strcpy(Zeilenpuf, "  ");
			i = 0;
			/* Nun zu den Disketten selbst						*/
			while( n->ln_Succ )
			{
				/* Zunächst holen wir mal die Diskbezeichn.,	*/
				n = n->ln_Succ;
				a = (struct VDBnode *) gt_GetListEntry( &vdblist, i );
				i++;
				/* schaun ob in der Zeile noch Platz ist,		*/
				if((strlen(a->d.Name) + strlen(Zeilenpuf)) > 52 )
				{
					/* wenn nicht, drucken wir die alte und	*/
					strcat( Schreibpuf, Zeilenpuf );
					strcat( Schreibpuf, "\n");
					/* beginnen eine neue							*/
					strcpy(Zeilenpuf, "  ");
				}
				/* nun können wir getrost die Diskettenbez.	*/
				strcat(Zeilenpuf, a->d.Name);
				/* gefolgt von einem Komma dranhängen			*/
				strcat(Zeilenpuf, ", ");
			}
			/* Da die letzte Zeile nicht gedruckt wurde,		*/
			/* holen wir das nach und								*/
			strcat( Schreibpuf, Zeilenpuf );
			/* hängen eine Leerzeile dran.						*/
			strcat( Schreibpuf, "\n\n" );
			/* In der Hoffnung das es auch wirklich flott	*/
			/* geht, danken wir dafür schon im Voraus,		*/
			strcat(Schreibpuf, "  Vielen Dank für die schnelle Bearbeitung\f");
			if (fputs( Schreibpuf, os ) == DOSTRUE)
			{
				/* Schreiben klappte nicht							*/
				es.es_Title			= "Problem!";
				es.es_TextFormat	= "Fehler beim Drucken/Speichern aufgetreten!";
				es.es_GadgetFormat= "Abbrechen";

				EasyRequest(BestellenWnd, &es, NULL);
			}
		}
		/* und schließen die Datei wieder						*/
		fclose(os);
	}
	/* Konnte die Datei jedoch nicht geöffnet werden,		*/
	else
	{
		/* wird der Benuter per Requester Informiert			*/
		es.es_Title			= "Problem!";
		es.es_TextFormat	= "Kann leider den Drucker oder Datei nicht ansprechen!";
		es.es_GadgetFormat= "Abbrechen";

		EasyRequest(BestellenWnd, &es, NULL);
	}
}

/* Window mit den Voreingestellten Daten füllen				*/
void Winfuell()
{
	/* Daten in das ListView Gadget einbauen					*/
	gt_AttachList( BestellenGadgets[GD_Diskliste], BestellenWnd, &vdblist );

	/* Voreinstellungen einbauen									*/
	GT_SetGadgetAttrs( BestellenGadgets[ GD_Zahlart ], BestellenWnd, NULL, 
								GTMX_Active, P1.Versart,
								TAG_DONE);
	gt_SetString( BestellenGadgets[ GD_AName ], BestellenWnd, P1.AName );
	gt_SetString( BestellenGadgets[ GD_AStrasse ], BestellenWnd, P1.AStrasse);
	gt_SetString( BestellenGadgets[ GD_AOrt ], BestellenWnd, P1.AOrt);
	gt_SetString( BestellenGadgets[ GD_KundNr ], BestellenWnd, P1.KundNr );

	gt_SetString( BestellenGadgets[ GD_EName ], BestellenWnd, P1.EName );
	gt_SetString( BestellenGadgets[ GD_EStrasse ], BestellenWnd, P1.EStrasse);
	gt_SetString( BestellenGadgets[ GD_EOrt ], BestellenWnd, P1.EOrt);

	gt_SetInteger( BestellenGadgets[ GD_Abstand ], BestellenWnd, P1.Abstand);
	/* momentan nicht benötigte Gadgets sperren				*/
	checkonoff();
}

/* Wenn jemand versucht ein Gadget zu erdrücken				*/
BOOL Abfrage_Gadgetup( struct Gadget *gad, long code)
{
	char Merken[15];
	long i = 0;
	BOOL terminated = FALSE;	

	/* Wenn die Help-Taste der Grund fürs Beenden des G.	*/
	if(code==95)
	{
		/* Rufen wir die Rawkey-Abfrage auf (HELP-Behandl.)*/
		Abfrage_Rawkey(code,gad);
		/* mehr gibts nicht zu tun, also ab nach Hause		*/
		return terminated;
	}

	/* mal sehen, auf welches G. der User es abgesehen hat*/
	switch( gad->GadgetID )
	{
		/* Jemand hat auf die Liste geklickt					*/
		case GD_Diskliste:
			/* dann gibts einen neuen aktuellen Eintrag		*/
			currentvdb = (struct VDBnode *) gt_GetListEntry( &vdblist, code );
			/* eventuell gesperrte Gadgets freigeben			*/
			checkonoff();
			/* Stringgadget unter der Liste füllen				*/
			gt_SetString( BestellenGadgets[GD_DiskAender], BestellenWnd, currentvdb->d.Name );
			/* und aktivieren											*/
			ActivateGadget( BestellenGadgets[GD_DiskAender], BestellenWnd, NULL );
			break;

		/* Jemand will ne neue Disk eingeben					*/
		case GD_NeueDisk:
			/* Dafür haben wir ein Unerprogramm					*/
			newvdb();
			break;

		/* Jemand will ne Disk löschen							*/
		case GD_DiskLoeschen:
			/* auch dafür gibts ein Unterprogramm				*/
			EintragLoeschen();
			break;
		/* Zahlart wurde geändert									*/
		case GD_Zahlart:
			/* einfach nur merken, das reicht schon			*/
			P1.Versart = code;
			break;
		/* Drucken														*/
		case GD_Drucken:
			/* Druckroutine aufrufen								*/
			Drucken(&vdblist, "PRT:");
			break;
		/* Abbrechen													*/
		case GD_Abbrechen:
			/* zurückgeben, daß der User keine Lust mer hat	*/
			terminated = TRUE;
			break;
		/* Absendername												*/
		case GD_AName:
			/* Einfach nur den neuen Namen merken				*/
			strcpy( P1.AName, gt_GetString( BestellenGadgets[ GD_AName ]) );
			break;
		/* Absenderstraße												*/
		case GD_AStrasse:
			/* Einfach nur die neue Straße merken				*/
			strcpy( P1.AStrasse, gt_GetString( BestellenGadgets[ GD_AStrasse ]) );
			break;
		/* Absenderort													*/
		case GD_AOrt:
			/* Einfach nur den Ort merken							*/
			strcpy( P1.AOrt, gt_GetString( BestellenGadgets[ GD_AOrt ]) );
			break;
		/* Kundennummer												*/
		case GD_KundNr:
			/* Einfach nur die Kundennummer merken				*/
			strcpy( P1.KundNr, gt_GetString( BestellenGadgets[ GD_KundNr ]) );
			break;
		/* Empfängername												*/
		case GD_EName:
			/* Einfach nur den Namen merken						*/
			strcpy( P1.EName, gt_GetString( BestellenGadgets[ GD_EName ]) );
			break;
		/* Empfängerstrasse											*/
		case GD_EStrasse:
			/* Einfach nur die Strasse merken					*/
			strcpy( P1.EStrasse, gt_GetString( BestellenGadgets[ GD_EStrasse ]) );
			break;
		/* Empfängerort												*/
		case GD_EOrt:
			/* Einfach nur den Ort merken							*/
			strcpy( P1.EOrt, gt_GetString( BestellenGadgets[ GD_EOrt ]) );
			break;
		/* Diskette neu angelegt oder alte ändern				*/
		case GD_DiskAender:
			/* Den neuen Namen Merken								*/
			strcpy(Merken, gt_GetString( BestellenGadgets[ GD_DiskAender ]) );
			/* Wenn er sich nicht geändert hat, ignorieren	*/
			if(strcmp(currentvdb->d.Name, Merken)==0) {}
			/* aber sonst												*/
			else
			{
				/* löschen wir den alten Eintrag					*/
				EintragLoeschen();
				/* Hängen die Liste ab								*/
				gt_AttachList( BestellenGadgets[GD_Diskliste], BestellenWnd, (struct List *) ~0 );
				/* den neuen Eintrag an (Position merken)		*/
				i = NeuerEintrag( Merken );
				/* hängen die Liste wieder dran					*/
				gt_AttachList( BestellenGadgets[GD_Diskliste], BestellenWnd, &vdblist );
				/* aktivieren den neuen Eintrag					*/
				gt_SetLV( BestellenGadgets[GD_Diskliste], BestellenWnd, i );
				/* merken ihn uns als aktuellen					*/
				currentvdb = (struct VDBnode *) gt_GetListEntry( &vdblist, i );
				/* schalten alle Gadgets an und					*/
				checkonoff();
				/* setzen den Namen ins Feld unter der Liste	*/
				gt_SetString( BestellenGadgets[GD_DiskAender], BestellenWnd, currentvdb->d.Name );
			}
			break;
		/* Abstand fürs Drucken										*/
		case GD_Abstand:
			/* Den Abstand einfach nur merken					*/
			P1.Abstand = gt_GetInteger( BestellenGadgets[ GD_Abstand ]);
			break;
		/* Dürfte nicht vorkommen, aber sicher ist sicher!	*/
		default:
			break;
	}
	/* Und ab nach Hause, mit rückgabewert, ob Schluß ist	*/
	return(terminated);
}

/* Jemand hat das Menu benutzt									*/
BOOL Abfrage_Menuepick( UWORD code)
{
	/* Struktur für den Requester, falls wir ihn brauchen	*/
	struct MenuItem *item;
	BOOL terminated = FALSE;
	item = ItemAddress(BestellenMenus, code);
	/* mal schaun, was ausgewählt wurde							*/
	switch ( (int)MENU_USERDATA(item) )
	{
		/* Menupunkt Speichern										*/
		case MENU_FOO_SPE:
			/* Gut, schreiben wir mal die Einstellungen		*/
			Drucken(&vdblist, filename);
			break;

		/* Menupunkt Speichern als ...							*/
		case MENU_FOO_SSP:
			/* Wenn die Asl.library geöffnet werden konnte	*/
			if( AslBase != NULL )
			{
				/* Öffne einen einfachen Filerequester			*/
				if (fr = ( struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
																						TAG_DONE))
				{
					if(AslRequest(fr,NULL))
					{
						/* Der neue Filerequester setzt sich	*/
						/* aus Drawer und File zusammen.			*/
						strcpy(filename, fr->fr_Drawer);
						strcat(filename, fr->fr_File);
						/* Gut, schreibe die Bestellung			*/
						Drucken(&vdblist, filename);
					}
					FreeAslRequest(fr);
				}
			}
			else
			{
				/* Schreib die Bestellung ins Standardverz.	*/
				Drucken(&vdblist, filename);
			}
			break;

		/* Menupunkt Drucken											*/
		case MENU_FOO_DRU:
			/* Unterprogramm zum Drucken starten				*/
			Drucken(&vdblist, "PRT:");
			break;

		/* Menupunkt Information									*/
		case MENU_FOO_INF:
			/* Starten wir nen kleinen Inforequester			*/
			es.es_StructSize	= sizeof(struct EasyStruct);
			es.es_Flags			= 0;
			es.es_Title			= "Über T_Bestellen";
			es.es_TextFormat	= "   T_Bestellen (Version 1.33)\n©1994-95 by MT Graphic & Design\n\nProgrammiert von Manfred Tremmel\n";
			es.es_GadgetFormat= "Weiter gehts!";

			EasyRequest(BestellenWnd, &es, NULL);
			break;

		/* Menupunkt Programm beenden								*/
		case MENU_FOO_END:
			/* gut, Rückgabewert auf Ende setzen				*/
			terminated = TRUE;
			break;

		/* Sollte nicht vorkommen									*/
		default:
			break;
	}
	/* Rückgabewert, ob der User weitermachen will			*/
	return(terminated);
}

/* Eine handelsübliche Taste wurde gedrückt					*/
BOOL Abfrage_Vanillakey(UWORD code)
{
	BOOL terminated = FALSE;	

	/* Wollen wir doch mal sehen, welche da benutzt wurde	*/
	switch(code)
	{
		case 'i':
		case 'I':
			/* ist ein Eintrag in der liste ausgewählt?		*/
			if( currentvdb )
				/* ja, dann aktivire das Feld unter der Liste*/
				ActivateGadget( BestellenGadgets[GD_DiskAender], BestellenWnd, NULL );
			else if(gt_GetListNumEntries( &vdblist ) > 0)
			{
				/* nein, dann selektiere den ersten Eintrag	*/
				currentvdb = (struct VDBnode *) gt_GetListEntry(&vdblist, 0);	
				gt_SetLV(BestellenGadgets[GD_Diskliste], BestellenWnd, gt_GetListEntryNum(&vdblist, (struct Node *) currentvdb));
				/* aktiviere alle Gadgets							*/
				checkonoff();
				/* und setz den Disknamen ins String-Gadget	*/
				gt_SetString( BestellenGadgets[GD_DiskAender], BestellenWnd, currentvdb->d.Name );
			}
			break;

		/* Neuer Listeneintrag										*/
		case 'e':
		case 'E':
			/* dafür haben wir doch ein Unterprogramm			*/
			newvdb();
			break;

		/* Jemand will ne Disk löschen							*/
		case 'h':
		case 'H':
			/* Nur wenn ein Eintrag aktiviert ist löschen	*/
			if( currentvdb )
				EintragLoeschen();
			break;

		/* Drucken														*/
		case 'd':
		case 'D':
			/* Druckroutine starten									*/
			Drucken(&vdblist, "PRT:");
			break;

		/* Abbrechen													*/
		case 'a':
		case 'A':
			/* Wenn er nimmer will, halten wir ihn nicht auf*/
			terminated = TRUE;
			break;

		/* Absendername												*/
		case 'n':
		case 'N':
			ActivateGadget( BestellenGadgets[GD_AName], BestellenWnd, NULL );
			break;

		/* Absenderstraße												*/
		case 's':
		case 'S':
			ActivateGadget( BestellenGadgets[GD_AStrasse], BestellenWnd, NULL );
			break;

		/* Absenderort													*/
		case 'o':
		case 'O':
			ActivateGadget( BestellenGadgets[GD_AOrt], BestellenWnd, NULL );
			break;

		/* Kundennummer												*/
		case 'k':
		case 'K':
			ActivateGadget( BestellenGadgets[GD_KundNr], BestellenWnd, NULL );
			break;

		/* Empfängername												*/
		case 'm':
		case 'M':
			ActivateGadget( BestellenGadgets[GD_EName], BestellenWnd, NULL );
			break;

		/* Empfängerstraße											*/
		case 't':
		case 'T':
			ActivateGadget( BestellenGadgets[GD_EStrasse], BestellenWnd, NULL );
			break;

		/* Empfänger Postleitzahl/Ort								*/
		case 'p':
		case 'P':
			ActivateGadget( BestellenGadgets[GD_EOrt], BestellenWnd, NULL );
			break;

		/* Leerzeilen vorm Ausdruck								*/
		case 'l':
		case 'L':
			ActivateGadget( BestellenGadgets[GD_Abstand], BestellenWnd, NULL );
			break;

		/* Zahlungsart Nachnahme									*/
		case 'c':
		case 'C':
			P1.Versart = 0;
			GT_SetGadgetAttrs( BestellenGadgets[ GD_Zahlart ], BestellenWnd, NULL, 
										GTMX_Active, P1.Versart,
										TAG_DONE);
			break;

		/* Zahlungsart Vorkasse										*/
		case 'v':
		case 'V':
			P1.Versart = 1;
			GT_SetGadgetAttrs( BestellenGadgets[ GD_Zahlart ], BestellenWnd, NULL, 
										GTMX_Active, P1.Versart,
										TAG_DONE);
			break;

		/* Zahlungsart Rechnung										*/
		case 'r':
		case 'R':
			P1.Versart = 2;
			GT_SetGadgetAttrs( BestellenGadgets[ GD_Zahlart ], BestellenWnd, NULL, 
										GTMX_Active, P1.Versart,
										TAG_DONE);
			break;

		/* andere Eingaben interressieren uns nicht			*/
		default:
			break;
	}
	/* under der obligatorische Rückgabewert					*/
	return(terminated);
}

/* eine der Tasten die nix aufm Bildschirm hinterlassen	*/
void Abfrage_Rawkey( UWORD code, struct Gadget *gd)
{
	int i;

	/* Ein paar Sachen für einen AmigaGude aufruf			*/
	struct NewAmigaGuide sync = {NULL};
	static UBYTE *AG_ID[] = {
		"GD_Diskliste",
		"GD_NeueDisk",
		"GD_DiskLoeschen",
		"GD_Zahlart",
		"GD_Drucken",
		"GD_Abbrechen",
		"GD_AName",
		"GD_AStrasse",
		"GD_AOrt",
		"GD_KundNr",
		"GD_EName",
		"GD_EStrasse",
		"GD_EOrt",
		"GD_DiskAender",
		"GD_Abstand",
	};

	AMIGAGUIDECONTEXT MyHandle;

	switch ( code )
	{
		/* Cursor hoch (Listview hoch)							*/
		case 76:
			/* sollte überhaupt ein Eintrag aktiv sein		*/
			if( currentvdb )
			{
				/* kucken wir, welche Nummer der hat			*/
				i = gt_GetListEntryNum( &vdblist, (struct Node *) currentvdb );
				/* senken die Nummer um 1 und						*/
				i--;
				/* sollten wir noch nicht ganz oben sein		*/
				if(i >= 0)
				{
					/* haben wir einen neuen aktuellen Eintr.	*/
					currentvdb = (struct VDBnode *) gt_GetListEntry(&vdblist, i);	
					gt_SetLV(BestellenGadgets[GD_Diskliste], BestellenWnd, gt_GetListEntryNum(&vdblist, (struct Node *) currentvdb));
					/* ab damit ins Feld unter der Liste		*/
					gt_SetString( BestellenGadgets[GD_DiskAender], BestellenWnd, currentvdb->d.Name );
				}
			}
			break;

		/* Cursor hoch (Listview hoch)							*/
		case 77:
			/* sollte überhaupt ein Eintrag aktiv sein		*/
			if( currentvdb )
			{
				/* kucken wir, welche Nummer der hat			*/
				i = gt_GetListEntryNum( &vdblist, (struct Node *) currentvdb );
				/* erhöhen die Nummer um 1 und					*/
				i++;
				/* sollten wir noch nicht ganz unten sein,	*/
				if(i < gt_GetListNumEntries( &vdblist ))
				{
					/* haben wir einen neuen aktuellen Eintr.	*/
					currentvdb = (struct VDBnode *) gt_GetListEntry(&vdblist, i);	
					/* ab damit ins Feld unter der Liste		*/
					gt_SetLV(BestellenGadgets[GD_Diskliste], BestellenWnd, gt_GetListEntryNum(&vdblist, (struct Node *) currentvdb));
					gt_SetString( BestellenGadgets[GD_DiskAender], BestellenWnd, currentvdb->d.Name );
				}
			}
			break;

		/* Help-Taste gedrückt										*/
		case 95:
			/* Ist die AmigaGuide Library geöffnet + OS 3.x	*/
			if( AmigaGuideBase != NULL )
			{
				/* Legen wir die Guide-Datei fest				*/
				sync.nag_Name	= "T_Bestellen.guide";

				/* steht der Mauszeiger über keinem Gadget,	*/
				if(gd == NULL)
					/* den defaultmäßigen Node setzen			*/
					sync.nag_Node	= "Window";
				/* steht der Mauszeiger über einem Gadget,	*/
				else
					/* wird dar passende Node gesetzt			*/
					sync.nag_Node = AG_ID[gd->GadgetID];

				/* Gut, öffnen wir die Guide Datei				*/
				MyHandle = OpenAmigaGuide( &sync, NULL );

				/* und schließen sie, wenn's öffnen klappte	*/
				if(MyHandle)
					CloseAmigaGuide( MyHandle);

			}
			/* Ist die AmigaGuide Library nicht zu öffnen,	*/
			else
			{
				/* gibts ne Message, daß ohne AmigaGuide nix	*/
				/* los ist mit der OnlineHilfe					*/
				es.es_StructSize	= sizeof(struct EasyStruct);
				es.es_Flags			= 0;
				es.es_Title			= "Fehler";
				es.es_TextFormat	= "Online-Hilfe leider nur mit AmigaGuide.library verfügbar";
				es.es_GadgetFormat= "Hilft nix";

				EasyRequest(BestellenWnd, &es, NULL);
			}
			break;

		/* Sonstige Tasten jucken mich derzeit nicht			*/
		default:
			break;
	}
}

/* eine der Tasten die nix aufm Bildschirm hinterlassen	*/
void Abfrage_Menuhelp( UWORD code)
{
	/* Ein paar Sachen für einen AmigaGude aufruf			*/
	struct NewAmigaGuide sync = {NULL};

	AMIGAGUIDECONTEXT MyHandle;

	/* Ist die AmigaGuide Library geöffnet + OS 3.x			*/
	if( AmigaGuideBase != NULL )
	{
		/* Legen wir die Guide-Datei fest						*/
		sync.nag_Name	= "T_Bestellen.guide";

		/* steht der Mauszeiger über einem Menüpunkt?		*/
		switch(code)
		{
			/* HELP beim Menü-Punkt Speichern					*/
			case 63488:
				sync.nag_Node	= "Menu_Spe";
				break;
			/* HELP beim Menü-Punkt Speichern als ...			*/
			case 63520:
				sync.nag_Node	= "Menu_Ssp";
				break;
			/* HELP beim Menü-Punkt Drucken						*/
			case 63552:
				sync.nag_Node	= "Menu_Dru";
				break;
			/* HELP beim Menü-Punkt Über T_Bestellen ...		*/
			case 63616:
				sync.nag_Node	= "Menu_Inf";
				break;
			/* HELP beim Menü-Punkt Beenden						*/
			case 63680:
				sync.nag_Node	= "Menu_End";
				break;
			/* HELP außerhalb des Menüs, oder über Trennb.	*/
			default:
				sync.nag_Node	= "Window";
				break;
		}

		/* Gut, öffnen wir die Guide Datei						*/
		MyHandle = OpenAmigaGuide( &sync, NULL );

		/* und schließen sie, wenn's öffnen klappte			*/
		if(MyHandle)
			CloseAmigaGuide( MyHandle);

	}
	/* Ist die AmigaGuide Library nicht zu öffnen,			*/
	else
	{
		/* gibts ne Message, daß ohne AmigaGuide nix			*/
		/* los ist mit der OnlineHilfe							*/
		es.es_StructSize	= sizeof(struct EasyStruct);
		es.es_Flags			= 0;
		es.es_Title			= "Fehler";
		es.es_TextFormat	= "Online-Hilfe leider nur mit AmigaGuide.library verfügbar";
		es.es_GadgetFormat= "Hilft nix";

		EasyRequest(BestellenWnd, &es, NULL);
	}
}

/* Hauptprogramm														*/
int main( void )
{
	/* Hatt das öffnen der Libraries hingehauen?				*/
	if( OpenAll() == TRUE )
	{
		struct	IntuiMessage	*imsg;
		struct	Gadget *gad;
		struct	Gadget *gd = NULL;
		ULONG		imsgClass;
		UWORD		imsgCode;
		BOOL		Done = FALSE;

		/* Einstellungen lesen										*/
		EinstLesen();

		/* Daten lesen													*/
		DatenLesen();

		/* Bildschirm und Fenster öffnen							*/
		SetupScreen();
		OpenBestellenWindow();

		/* Window mit Voreinstellungen füllen					*/
		Winfuell();

		/* HelpControl unter 3.x starten, wegen der Hilfe	*/
		if( NOS )
		{
			HelpControl(BestellenWnd, HC_GADGETHELP);
		}

		/* Hauptschleife												*/
		while( !Done )
		{
			/* Auf IntuiMassage warten								*/
			WaitPort( BestellenWnd->UserPort );

			/* und Auswerten											*/
			while(imsg=GT_GetIMsg(BestellenWnd->UserPort))
			{
				imsgClass		= imsg->Class;
				imsgCode			= imsg->Code;
				gad = (struct Gadget *)imsg->IAddress;

				/* Jede empfangen Nachricht bestätigen			*/
				GT_ReplyIMsg(imsg);

				switch( imsgClass )
				{
					/* Windowschließsymbol gedrückt				*/
					case IDCMP_CLOSEWINDOW:
						Done = TRUE;
						break;

					/* Gadget gedrückt								*/
					case IDCMP_GADGETUP:
					case IDCMP_GADGETDOWN:
						Done = Abfrage_Gadgetup(gad, imsgCode);
						break;

					/* Menupunkt ausgewählt							*/
					case IDCMP_MENUPICK:
						Done = Abfrage_Menuepick(imsgCode);
						break;

					/* gewähnliche Taste gedrückt					*/
					case IDCMP_VANILLAKEY:
						Done = Abfrage_Vanillakey(imsgCode);
						break;

					/* Mauszeiger ruht kurze Zeit über einem	*/
					/* Gadget => Gadget merken						*/
					case IDCMP_GADGETHELP:
						if( imsg->IAddress == (APTR) BestellenWnd ) 
							gd = NULL;
						else
							gd = gad;
						break;

					/* Während der Menüauswahl wurde die		*/
					/* Help-Taste gedrückt							*/
					case IDCMP_MENUHELP:
						Abfrage_Menuhelp( imsgCode);
						break;

					/* Steuertaste gedrückt							*/
					case IDCMP_RAWKEY:
						Abfrage_Rawkey(imsgCode,gd);
						break;

					/* Irgend was anderes, geht mich nichts an*/
					default:
						break;
				}
			}
		}

		/* Fenster und Bilschirm schließen						*/
		CloseBestellenWindow();
		CloseDownScreen();

		/* Einstellungen speichern									*/
		EinstSchreiben();

		/* Daten speichern und freigeben							*/
		DatenSchreiben();
	}
	/* Die Librareis konnten nicht (alle) geöffnet werden	*/
	else
	{
		/* Nachricht an den User, daß da was nicht stimmt	*/
		printf("Schon mal darüber nachgedacht, Deinem\nComputer ein neues Betriebssystem zu gönnen?\n");
	}
	/* geöffnete Libraries wieder schließen					*/
	CloseAll();

	/* 0 zurückgeben = alles glattgelaufen						*/
	return(0);
}
