/*
** Verwaltung der Auftragsliste
**
** Copyright (C) 1996 by Stefan Scherer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for non-commerical use and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation.  This software is provided "as is" without
** express or implied warranty.
*/

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include <exec/types.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <exec/nodes.h>
#include <dos/exall.h>
#include <clib/alib_protos.h>
#include <proto/exec.h>

#include "AuftragsListe.h"
#include "LocaleSupport.h"
#include "MiscSupport.h"

#define MAX_LINE_LEN 100

/* die kleinste Jahreszahl, ab der die Aufträge verwaltet werden können */

#define BASE_YEAR 1993

/* der Pfadname für jeden Jahrgang. Die Jahreszahl wird noch angehängt */

#define BASE_DIR  "Aufträge"


/* die Liste enthält Node-Strukturen mit den Auftragsdaten */

struct OrderNode
  {
    struct Node Node;
    struct MinOrder order;
  };


/* jeder Jahrgang wird zusätzlich verwaltet */

struct YearNode
  {
    struct Node Node;		/* Node zum verketten */
    struct List List;		/* Liste aller Aufträge in diesem Jahr */
    struct OrderNode *aktOrder;	/* der aktuelle Auftrag */
    UWORD itemCount;		/* Anzahl Aufträge in diesem Jahr */
    UWORD aktNummer;		/* Nummer des aktuellen Eintrags in Liste */
    UWORD Year;			/* das Jahr selbst (z.B. 1994) */
  };


static struct YearNode *aktList;
static struct List orderYears;
static UWORD yearCount;

/* Zeiger auf den Memory-Pool */

static void *poolHeader = NULL;	/* Zeiger für Memory-Pool */


/* private Prototypen */

static int ReadDir (UWORD year);
static int WriteDir (UWORD year);
static int CompareNumbers (struct OrderNode *l, struct OrderNode *r);
static int private_NewOrder (struct MinOrder *item);


/* intern wird ein Status mitgeführt, der anzeigt, was alles geladen wurde */

enum
  {
    STATUS_NOTHING,		/* es wurde noch nichts geladen */
    STATUS_LISTS		/* es wurden alle Auftragslisten geladen */
  };

static int status;


/* Fehlercode und Fehlerstrings */

static int error;
static const STRPTR errormsg[] =
{
  "",				// ERR_OL_OK
   "ungültiges Jahr",		// ERR_OL_YEAR
   "Liste leer",		// ERR_OL_LISTEMPTY
   "Eintrag nicht in Liste",	// ERR_OL_NOITEM
   "kein Speicher",		// ERR_OL_NOMEM
   "kein memorypool",		// ERR_OL_NOPOOL
   "Fehler bei Verzeichnis",	// ERR_OL_NOPATH
   "Fehler bei ExAll()",	// ERR_OL_EXALL
   "",				// ERR_OL_ORDER -> O_GetErrorMsg()
   "Fehler bei Datei 'AuftragsListe'",	// ERR_OL_FILELIST
   "Fehler beim speichern",	// ERR_OL_SAVE
};


int 
ConstructOrderList (void)
{
  int i;
  ULONG year;

  NewList (&orderYears);
  aktList = NULL;
  yearCount = 0;

  status = STATUS_NOTHING;

  /* neuen Memory-Pool anfordern */

  if (!(poolHeader = LibCreatePool (MEMF_CLEAR, 4000, 4000)))
    return (error = ERR_OL_NOPOOL);

  /* Files einlesen */

  year = GetThisYear ();
  for (i = BASE_YEAR; i < year; i++)
    {
      /* fügt ein Jahr in die Liste ein und dort noch die Aufträge */
      ReadDir (i);
    }

  ReadDir (year);

  status = STATUS_LISTS;

  OL_SetYear (year);

  return (error = ERR_OL_OK);
}


/*
** alles aufräumen
*/

void 
DestructOrderList (void)
{
// wird bereits beim Ändern eines Auftrags gespeichert...
//   UWORD year, i;
//
//   if( status == STATUS_LISTS )
//   {
//         /* Files speichern */
//
//         year = GetThisYear();
//         for( i = BASE_YEAR; i <= year; i++ )
//         {
//            /* schreibt alle Listen der Jahrgänge in Files */
//            WriteDir( i );
//         }
//      }

  if (poolHeader)
    {
      LibDeletePool (poolHeader);
      poolHeader = NULL;
    }
}


/*
** Setze den aktuellen Jahrgang
*/

int 
OL_SetYear (UWORD year)
{
  struct YearNode *node;

  for (node = (struct YearNode *) orderYears.lh_Head;
       node->Node.ln_Succ && (year != node->Year);
       node = (struct YearNode *) node->Node.ln_Succ);

  if (node->Node.ln_Succ)
    {
      aktList = node;
      return (error = ERR_OL_OK);
    }
  else
    return (error = ERR_OL_YEAR);
}


/*
** ermittle das aktuelle Jahr
*/

UWORD 
OL_GetCurrentYear (void)
{
  if (!aktList)
    return (0);

  return (aktList->Year);
}


/*
** ermittle ein bestimmtes Jahr
*/

int 
OL_GetYear (UWORD num, UWORD * year)
{
  int i;
  struct YearNode *node;

  if (yearCount == 0)
    return (error = ERR_OL_YEAR);

  if (num >= yearCount)
    return (error = ERR_OL_YEAR);

  for (i = 0, node = (struct YearNode *) orderYears.lh_Head;
       i < num && node->Node.ln_Succ;
       i++, node = (struct YearNode *) node->Node.ln_Succ);

  *year = node->Year;
  return (error = ERR_OL_OK);
}


/*
** bestimme die Nummer des aktuellen Jahres in der Liste
*/

UWORD 
OL_GetCurrentYearNumber (void)
{
  UWORD i;
  struct YearNode *node;

  if (yearCount == 0)
    return (0);

  for (i = 0, node = (struct YearNode *) orderYears.lh_Head;
       node->Node.ln_Succ && (aktList->Year != node->Year);
       i++, node = (struct YearNode *) node->Node.ln_Succ);

  return (i);
}


/*
** ermittle die Anzahl der Jahre
*/

UWORD 
OL_GetYearCount (void)
{
  return (yearCount);
}


/*
** neuen Auftrag in die Liste übernehmen 
*/

static int 
private_NewOrder (struct MinOrder *item)
{
  struct OrderNode *newitem;
  int result = ERR_OL_OK;

  if (!(newitem = LibAllocPooled (poolHeader, sizeof (struct OrderNode))))
      return (error = ERR_OL_NOMEM);

  newitem->order.orderNumber = item->orderNumber;
  newitem->order.orderYear = item->orderYear;
  strcpy (newitem->order.orderDate, item->orderDate);
  strcpy (newitem->order.Kunde, item->Kunde);
  newitem->order.invoiceNumber = item->invoiceNumber;
  newitem->order.invoiceYear = item->invoiceYear;
  strcpy (newitem->order.invoiceDate, item->invoiceDate);

  AddTail (&aktList->List, (struct Node *) newitem);

  aktList->aktOrder = newitem;
  aktList->itemCount++;
  aktList->aktNummer = aktList->itemCount;	/* Zählung erfolgt von 1 ... */

  return (error = result);
}


/*
** Öffentlich: speichert zusätzlich noch die Auftragsliste ab
*/

int 
OL_NewOrder (struct MinOrder *item)
{
  int result;

  result = private_NewOrder (item);
  result = WriteDir (aktList->Year);

  return (error = result);
}


/*
** Auftrag aus Liste löschen
*/

int 
OL_DelOrder (void)
{
  struct OrderNode *newakt;
  char filename[80];
  int result;

  if (aktList->itemCount == 0)
    return (error = ERR_OL_LISTEMPTY);

  /* File auch noch löschen */
  sprintf (filename, "%s%04d/%03d.%s", BASE_DIR,
   aktList->aktOrder->order.orderYear, aktList->aktOrder->order.orderNumber,
	   aktList->aktOrder->order.Kunde);
  unlink (filename);

  if (aktList->aktNummer == aktList->itemCount)
    {
      if (aktList->itemCount > 1)
	newakt = (struct OrderNode *) aktList->aktOrder->Node.ln_Pred;
      else
	newakt = NULL;

      RemTail (&aktList->List);
      LibFreePooled (poolHeader, aktList->aktOrder, sizeof (struct OrderNode));
      aktList->aktNummer--;
      aktList->itemCount--;
      aktList->aktOrder = newakt;
    }
  else
    {
      if (aktList->itemCount > 1)
	newakt = (struct OrderNode *) aktList->aktOrder->Node.ln_Succ;
      else
	{
	  newakt = NULL;
	  aktList->aktNummer = 0;
	}

      Remove ((struct Node *) aktList->aktOrder);
      LibFreePooled (poolHeader, aktList->aktOrder, sizeof (struct OrderNode));
      aktList->itemCount--;
      aktList->aktOrder = newakt;
    }
  /* Änderung auch im File machen */
  result = WriteDir (aktList->Year);

  return (error = result);
}


/*
** aktuellen Auftragsdaten in der Liste ändern
*/

int 
OL_ChangeOrder (struct MinOrder *item)
{
  int result;

  if (aktList->itemCount == 0)
    return (error = ERR_OL_LISTEMPTY);

  aktList->aktOrder->order.orderNumber = item->orderNumber;
  aktList->aktOrder->order.orderYear = item->orderYear;
  strcpy (aktList->aktOrder->order.orderDate, item->orderDate);
  strcpy (aktList->aktOrder->order.Kunde, item->Kunde);
  aktList->aktOrder->order.invoiceNumber = item->invoiceNumber;
  aktList->aktOrder->order.invoiceYear = item->invoiceYear;
  strcpy (aktList->aktOrder->order.invoiceDate, item->invoiceDate);

  result = WriteDir (aktList->Year);

  return (error = result);
}


/*
** mache den Auftrag mit der Nummer 'number' zum aktuellen
**
** das ist NICHT die Position in der Liste !
*/

int 
OL_SetCurrentOrderNumber (UWORD number)
{
  int i;
  struct OrderNode *node;

  if (aktList->itemCount == 0)
    return (error = ERR_OL_LISTEMPTY);

  for (i = 0, node = (struct OrderNode *) aktList->List.lh_Head;
       node->Node.ln_Succ && (node->order.orderNumber != number);
       i++, node = (struct OrderNode *) node->Node.ln_Succ);

  if (node->Node.ln_Succ)
    {
      aktList->aktOrder = node;
      aktList->aktNummer = i + 1;
      return (error = ERR_OL_OK);
    }
  else
    return (error = ERR_OL_NOITEM);
}


/*
** lies die Anzahl der Aufträge im aktuellen Jahr
*/

UWORD 
OL_GetOrderCount (void)
{
  return (aktList->itemCount);
}


/*
** lies die Daten eines Auftrags im aktuellen Jahr
*/

int 
OL_GetOrder (UWORD num, struct MinOrder *item)
{
  struct OrderNode *node;
  int i;

  if (aktList->itemCount == 0)
    return (error = ERR_OL_LISTEMPTY);

  if (num >= aktList->itemCount)
    return (error = ERR_OL_NOITEM);

  for (i = 0, node = (struct OrderNode *) aktList->List.lh_Head;
       i < num && node->Node.ln_Succ;
       i++, node = (struct OrderNode *) node->Node.ln_Succ);

  item->orderNumber = node->order.orderNumber;
  item->orderYear = node->order.orderYear;
  strcpy (item->orderDate, node->order.orderDate);
  strcpy (item->Kunde, node->order.Kunde);
  item->invoiceNumber = node->order.invoiceNumber;
  item->invoiceYear = node->order.invoiceYear;
  strcpy (item->invoiceDate, node->order.invoiceDate);

  return (error = ERR_OL_OK);
}


/*
** lies die Daten des aktuellen Auftrags im aktuellen Jahr
*/

int 
OL_GetCurrentOrder (struct MinOrder *item)
{
  if (aktList->itemCount == 0)
    return (error = ERR_OL_LISTEMPTY);

  item->orderNumber = aktList->aktOrder->order.orderNumber;
  item->orderYear = aktList->aktOrder->order.orderYear;
  strcpy (item->orderDate, aktList->aktOrder->order.orderDate);
  strcpy (item->Kunde, aktList->aktOrder->order.Kunde);
  item->invoiceNumber = aktList->aktOrder->order.invoiceNumber;
  item->invoiceYear = aktList->aktOrder->order.invoiceYear;
  strcpy (item->invoiceDate, aktList->aktOrder->order.invoiceDate);

  return (error = ERR_OL_OK);
}


/*
** ermittle die Auftrags-Nummer des aktuellen Eintrags in der Liste
**
** das ist NICHT die Nummer (=Position) in der Liste!
*/

int 
OL_GetCurrentOrderNumber (void)
{
  if (aktList->aktOrder)
    return (aktList->aktOrder->order.orderNumber);
  else
    return (0);
}


/*
** Lies das Directory anhand des angegebenen Jahrganges ein
** und baue die Auftrags-Liste auf.
*/

static int 
ReadDir (UWORD year)
{
  struct YearNode *newitem;
  char dirname[30];
  char filename[60];
  FILE *file;
  BPTR lock;
  BOOL ok = TRUE;
  struct MinOrder minorder;
  char buffer[MAX_LINE_LEN];
  STRPTR p;
  int result = ERR_OL_OK;

  if (!(newitem = LibAllocPooled (poolHeader, sizeof (struct YearNode))))
      return (error = ERR_OL_NOMEM);

  newitem->Year = year;
  NewList (&newitem->List);
  newitem->aktOrder = NULL;
  newitem->aktNummer = 0;
  AddTail (&orderYears, (struct Node *) newitem);
  yearCount++;

  OL_SetYear (year);

  /* Directory einlesen und im Jahrgang einfügen */
  /* wenn Dir nicht vorhanden, dann neu anlegen */

  sprintf (dirname, "%s%04d", BASE_DIR, year);
  sprintf (filename, "%s%04d/AuftragsListe", BASE_DIR, year);

  /* wenn Pfad nicht vorhanden, dann neu anlegen */
  if (!(lock = Lock (dirname, ACCESS_READ)))
    {
      lock = CreateDir (dirname);
    }

  if (lock)
    {
      /* Pfad vorhanden */

      if (file = fopen (filename, "r"))
	{
	  while (ok)
	    {
	      /*
	      ** · Auftragsjahr/nummer
	      */

	      if (ok && !fgets (buffer, MAX_LINE_LEN, file))
		ok = FALSE;
	      if (p = strchr (buffer, '\n'))
		*p = 0;

	      if (ok)
		{
		  STRPTR p;
		  if (p = strchr (buffer, '/'))
		    {
		      minorder.orderYear = atol (buffer);
		      minorder.orderNumber = atol (p + 1);
		    }
		  else
		    {
		      minorder.orderYear = 0;
		      minorder.orderNumber = 0;
		    }
		}

	      /*
	      ** · Auftragsdatum
	      */

	      if (ok && !fgets (minorder.orderDate, 12, file))
		ok = FALSE;
	      if (p = strchr (minorder.orderDate, '\n'))
		*p = 0;

	      /*
	      ** · Kunde
	      */

	      if (!fgets (minorder.Kunde, 100, file))
		ok = FALSE;
	      if (p = strchr (minorder.Kunde, '\n'))
		*p = 0;

	      /*
	      ** · Rechnungsjahr/nummer
	      */

	      if (ok && !fgets (buffer, MAX_LINE_LEN, file))
		ok = FALSE;
	      if (p = strchr (buffer, '\n'))
		*p = 0;

	      if (ok)
		{
		  STRPTR p;
		  if (p = strchr (buffer, '/'))
		    {
		      minorder.invoiceYear = atol (buffer);
		      minorder.invoiceNumber = atol (p + 1);
		    }
		  else
		    {
		      minorder.invoiceYear = 0;
		      minorder.invoiceNumber = 0;
		    }
		}

	      /*
	      ** · Rechnungsdatum
	      */

	      if (ok && !fgets (minorder.invoiceDate, 12, file))
		ok = FALSE;
	      if (p = strchr (minorder.invoiceDate, '\n'))
		*p = 0;

	      /*
	      ** · Leerzeile
	      */

	      if (ok && !fgets (buffer, MAX_LINE_LEN, file))
		ok = FALSE;

	      if (ok && private_NewOrder (&minorder))
		ok = FALSE;
	    }

	  fclose (file);
	}
      else
	{
	  /* "Auftragsliste" ist noch nicht vorhanden, also
	  ** neu aufbauen
	  */

	  struct ExAllData *ead;
	  struct ExAllControl *eac;
	  struct OrderNode *newitem;
	  struct ExAllData *mem;
	  char patsrc[10], pattern[32];
	  BOOL more;
	  struct MinOrder minorder;

	  strcpy (patsrc, "???.#?");

	  eac = AllocDosObject (DOS_EXALLCONTROL, NULL);
	  if (eac)
	    {
	      if (mem = calloc (10000, 1))
		{
		  eac->eac_LastKey = 0;
		  ParsePatternNoCase (patsrc, pattern, 30);
		  eac->eac_MatchString = pattern;
		  do
		    {
		      more = ExAll (lock, mem, 10000, ED_NAME, eac);
		      if ((!more) && (IoErr () != ERROR_NO_MORE_ENTRIES))
			{
			  /* ExAll failed abnormally */
			  result = ERR_OL_EXALL;
			  break;
			}
		      if (eac->eac_Entries == 0)
			{
			  /* ExAll failed normally with no entries */
			  continue;	/* ("more" is *usually* zero) */
			}
		      ead = (struct ExAllData *) mem;
		      do
			{
			  /* use ead here */
			  sprintf (filename, "%s/%s", dirname, ead->ed_Name);
			  if (O_LoadOrder (filename))
			    result = ERR_OL_ORDER;

			  O_GetMinOrder (&minorder);

			  if (newitem = LibAllocPooled (poolHeader, sizeof (struct OrderNode)))
			    {
			      newitem->order.orderNumber = minorder.orderNumber;
			      newitem->order.orderYear = minorder.orderYear;
			      strcpy (newitem->order.orderDate, minorder.orderDate);
			      strcpy (newitem->order.Kunde, minorder.Kunde);
			      newitem->order.invoiceNumber = minorder.invoiceNumber;
			      newitem->order.invoiceYear = minorder.invoiceYear;
			      strcpy (newitem->order.invoiceDate, minorder.invoiceDate);

			      InsertSorted (&aktList->List, (struct Node *) newitem,
					    NULL, CompareNumbers);

			      aktList->aktOrder = (struct OrderNode *) aktList->List.lh_TailPred;
			      aktList->itemCount++;
			      aktList->aktNummer = aktList->itemCount;	/* Zählung erfolgt von 1 ... */
			    }
			  else
			    result = ERR_OL_NOMEM;

			  /* get next ead */
			  ead = ead->ed_Next;
			}
		      while (ead);

		    }
		  while (more);

		  free (mem);
		}
	      else
		result = ERR_OL_NOMEM;
	      FreeDosObject (DOS_EXALLCONTROL, eac);
	    }
	  else
	    result = ERR_OL_NOMEM;
	}

      /* Lock auf Directory nun freigeben */
      UnLock (lock);
    }
  else
    result = ERR_OL_NOPATH;

  return (error = result);
}


/*
** Schreibe die intern verwaltete Auftrags-Liste des angegebenen Jahres in
** ein File.
*/

static int 
WriteDir (UWORD year)
{
  char dirname[30];
  char filename[50];
  FILE *file;
  BPTR lock;
  BOOL ok = TRUE;
  struct OrderNode *node;
  int result = ERR_OL_OK;

  OL_SetYear (year);

  /* Jahrgang im File speichern */
  /* wenn Dir nicht vorhanden, dann neu anlegen */

  sprintf (dirname, "%s%04d", BASE_DIR, year);
  sprintf (filename, "%s%04d/AuftragsListe", BASE_DIR, year);

  /* wenn Pfad nicht vorhanden, dann neu anlegen */
  if (!(lock = Lock (dirname, ACCESS_READ)))
    {
      lock = CreateDir (dirname);
    }

  if (lock)
    {
      /* Pfad vorhanden */
      UnLock (lock);
      if (file = fopen (filename, "w"))
	{
	  for (node = (struct OrderNode *) aktList->List.lh_Head;
	       ok && node->Node.ln_Succ;
	       node = (struct OrderNode *) node->Node.ln_Succ)
	    {
	      /*
	      ** · Auftragsjahr/nummer
	      ** · Auftragsdatum
	      ** · Kunde
	      ** · Rechnungsjahr/nummer
	      ** · Rechnungsdatum
	      ** · Leerzeile
	      */

	      if (fprintf (file, "%04d/%d\n%s\n%s\n%04d/%d\n%s\n\n",
			   node->order.orderYear, node->order.orderNumber,
			   node->order.orderDate, node->order.Kunde,
			 node->order.invoiceYear, node->order.invoiceNumber,
			   node->order.invoiceDate) < 0)
		ok = FALSE;
	    }
	  if (!ok)
	    result = ERR_OL_SAVE;

	  fclose (file);
	}
      else
	result = ERR_OL_FILELIST;
    }
  else
    result = ERR_OL_NOPATH;

  return (error = result);
}


/*
** lade einen bestimmten Auftrag
*/

int 
OL_LoadOrder (struct MinOrder *minorder)
{
  char filename[150];
  int result = ERR_OL_OK;

  /* Filename: z.B.   "Aufträge1994/003.Scherer" */
  sprintf (filename, "%s%04d/%03d.%s", BASE_DIR, minorder->orderYear,
	   minorder->orderNumber, minorder->Kunde);

  if (O_LoadOrder (filename))
    result = ERR_OL_ORDER;

  return (error = result);
}


/*
** speichere einen bestimmten Auftrag
** und lösche (alte) Aufträge mit der selben Auftragsnummer
*/

int 
OL_SaveOrder (struct MinOrder *minorder)
{
  char filename[60];
  char dirname[30];
  char patsrc[10], pattern[32];
  BPTR lock;
  BOOL more;
  struct ExAllData *ead;
  struct ExAllControl *eac;
  struct ExAllData *mem;
  int result = ERR_OL_OK;

  /* Directory-Name und Pattern bestimmen */
  sprintf (dirname, "%s%04d", BASE_DIR, minorder->orderYear);
  sprintf (patsrc, "%03d.#?", minorder->orderNumber);


  /* wenn Pfad nicht vorhanden, dann neu anlegen */
  if (!(lock = Lock (dirname, ACCESS_READ)))
    {
      lock = CreateDir (dirname);
    }

  if (lock)
    {
      /* Pfad vorhanden */


      /* suche nach gleichen Auftragsnummern und lösche diese Dateien */

      eac = AllocDosObject (DOS_EXALLCONTROL, NULL);
      if (eac)
	{
	  if (mem = calloc (10000, 1))
	    {
	      eac->eac_LastKey = 0;
	      ParsePatternNoCase (patsrc, pattern, 30);
	      eac->eac_MatchString = pattern;
	      do
		{
		  more = ExAll (lock, mem, 10000, ED_NAME, eac);
		  if ((!more) && (IoErr () != ERROR_NO_MORE_ENTRIES))
		    {
		      /* ExAll failed abnormally */
		      result = ERR_OL_EXALL;
		      break;
		    }
		  if (eac->eac_Entries == 0)
		    {
		      /* ExAll failed normally with no entries */
		      continue;	/* ("more" is *usually* zero) */
		    }
		  ead = (struct ExAllData *) mem;
		  do
		    {
		      /* use ead here */
		      sprintf (filename, "%s/%s", dirname, ead->ed_Name);
		      unlink (filename);  /* lösche alle gefundenen Files */
		      /* get next ead */
		      ead = ead->ed_Next;
		    }
		  while (ead);

		}
	      while (more);

	      free (mem);
	    }
	  else
	    result = ERR_OL_NOMEM;
	  FreeDosObject (DOS_EXALLCONTROL, eac);
	}
      else
	result = ERR_OL_NOMEM;

      UnLock (lock);		/* Lock auf Directory freigeben */

      /* Filename: z.B.   "Aufträge1994/003.Scherer" */
      sprintf (filename, "%s%04d/%03d.%s", BASE_DIR, minorder->orderYear,
	       minorder->orderNumber, minorder->Kunde);

      if (O_SaveOrder (filename))
	result = ERR_OL_ORDER;

    }
  else
    result = ERR_OL_NOPATH;

  return (error = result);
}


/*
** lies die Auftragsnummer, die größer als die
** bisher größte ist. (saved+1)
*/

UWORD 
OL_GetNextOrderNumber (void)
{
  if (aktList)
    {
      if (IsListEmpty (&aktList->List))
	return (1);
      else
	return ((UWORD) (((struct OrderNode *)
	        (aktList->List.lh_TailPred))->order.orderNumber + 1));
    }
  return (0);
}



/*
** um die Einträge sortieren zu können, wird eine Vergleichsfunktion
** benötigt. Diese vergleich zwei Kundeneinträge miteinander und
** gibt einen Wert zurück, der dem Vergleich entspricht.
**
** mögliche Rückgabewerte:
**
**    l < r      l = r      l > r
**     -1          0          1
*/

static int 
CompareNumbers (struct OrderNode *l, struct OrderNode *r)
{
  return (l->order.orderNumber - r->order.orderNumber);
}


/*
** Fehlerstring holen 
*/

STRPTR 
OL_GetErrorMsg (void)
{
  if (error == ERR_OL_ORDER)
    return (O_GetErrorMsg ());
  else
    return (errormsg[error]);
}
