/*
** Druckerausgaben in TeX-Dateien und Aufruf von ShowDVI und DVIprint
**
** 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.
*/

#define MAX_LETTER_LEN 32000

#define PRINT_LOG_FILENAME "MUI-Rechnung.log"

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

#include <exec/types.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <utility/tagitem.h>
#include <proto/dos.h>
#include <proto/exec.h>

#include "Config.h"
#include "Print.h"
#include "Artikel.h"
#include "Kunden.h"
#include "Briefe.h"
#include "LocaleSupport.h"
#include "Rechnungsliste.h"
#include "Auftragsliste.h"


/* Prototypen aus dem TeX-Modul */

extern int invoiceinterface (int Positionsnummer,
			     char *Artikelnummer,
			     char *Artikelbezeichnung,
			     double *Einzelpreis,
			     double *Menge,
			     int *Preistabelle,
			     char *AppendString);


extern int invoiceTeXprintf (int Formularart,
			     char *Dateiname,	/* Basename */
			     int Rechnungsnummer,
			     int Rechnungsjahr,
			     int Anzahl_Positionen,
			     double MwSt1, double MwSt2,
			     int Kundennummer,
			     char Kundenanschrift[],
			     char Kundenkennzeichen[],
			     char Bestelldatum[],
			     int Adressaufkleber,
			     int Spracheinstellung, char *InsertString,
			     char Rechnungsdatum[]);

static BOOL printCustCategory (STRPTR category, ULONG mode, ULONG list,
                               FILE * file);
static BOOL printArticleCategory (STRPTR category, ULONG mode, FILE * file);



/* lokale Prototypen */

static void ParseTeXLine (STRPTR line, UWORD len, BOOL command);
static void BuildLocaleString (STRPTR buffer);


/* TagList für Aufruf von SystemTagList() */

static struct TagItem DVIprintTags[] =
{
  SYS_Input, NULL,
  SYS_Output, NULL,
  TAG_DONE,
};

static char TheConWin[] =
   "CON:50/50/400/200/Bei Problemen mit 'CTRL \\' abbrechen...";

/*
** die Funktion, um die Artikelinformationen zu lesen wird
** bei jedem Ausdruck mit übergeben.
*/

static int (*GetArticle) (UWORD, struct Article *);


/* Fehlercode und Fehlerstrings */

static int error;
static const STRPTR errormsg[] =
{
  "",				//   ERR_PRINT_OK
   "Fehler beim TeX-Lauf",	//   ERR_PRINT_TEX
   "Pfad 'TeX:' nicht gefunden",	//   ERR_PRINT_PATH
   "Fehler bei Console",	//   ERR_PRINT_CON
   "interner TeX-Fehler",	//   ERR_PRINT_INTERNAL
   "Fehler beim Drucken",	//   ERR_PRINT_PRINTING
   "Fehler beim speichern",	//   ERR_PRINT_SAVE
};


/*
** Ausgaberoutine für TeX. Startet DVIprint
**
** Druckt die geladene Rechnung aus.
**
** Parameter:
**   mode     - gewünschter Formularmodus (siehe PRT_MODE_...)
**   pubname  - Name des Public Screens oder NULL
**   getfunc  - entsprechende Funktion, um einen Artikel zu holen
**   cust     - Zeiger auf den Kunden
**   count    - Anzahl der Artikel
**   number   - Nummer der Rechnung/Auftrag
**   invdate  - Datum der Rechnung
**   orddate  - Datum der Bestellung
**   mwst1,2  - Mehrwertsteuersätze für diesen Ausdruck
**   justshow - TRUE wenn ShowDVI laufen soll, FALSE wenn DVIprint
**              laufen soll
*/

int 
P_Print (UWORD mode, STRPTR pubname,
	 int (*getfunc) (UWORD, void *),
	 struct MinCustomer *cust, UWORD count, STRPTR number,
	 STRPTR invdate, STRPTR orddate, double mwst1, double mwst2,
	 BOOL justshow)
{
  unsigned char Anschrift[5 * MAX_PRINT_LEN];
  BPTR olddir, newdir, test;
  int result;
  char *Filename;
  STRPTR p;
  unsigned char zeichen[20];
  char bigbuf[2000];
  unsigned char ConWin[120];

  result = error = ERR_PRINT_OK;

  GetArticle = getfunc;

  sprintf (Anschrift, "%s\n%s\n%s\n%s\n%s", cust->Adresse1, cust->Adresse2,
	   cust->Adresse3, cust->Adresse4, cust->Adresse5);
  ParseTeXLine (Anschrift, 5 * MAX_PRINT_LEN - 1, FALSE);

  if (count > 0)
    {
      UWORD PrintNummer;
      UWORD RechnungsJahr;

      if (test = Lock ("texwork/invoice.tex", ACCESS_READ))
	{
	  /* file does exist */
	  UnLock (test);
	}
      else
	{
	  /* file does not exist, create it */
	  P_SaveConfig ();
	}

      if (newdir = Lock ("texwork", ACCESS_READ))
	{
	  olddir = CurrentDir (newdir);

	  RechnungsJahr = atoi (number);
	  if (p = strchr (number, '/'))
	    {
	      PrintNummer = atoi (p + 1);
	    }

	  switch (mode)
	    {
	    case PRT_MODE_CONFIRMATION:
	      if (justshow)
		Filename = "showAuftrag";
	      else
		Filename = "printAuftrag";
	      break;

	    default:
	      if (justshow)
		Filename = "showrechnung";
	      else
		Filename = "printrechnung";
	      break;
	    }

	  strcpy (zeichen, cust->Zeichen);
	  ParseTeXLine (zeichen, 19, FALSE);


	  /* 17.11.94: Spracheinstellungen per Programm speichern */
	  BuildLocaleString (bigbuf);

//              ParseTeXLine( bigbuf, 1999, FALSE );

	  if (!invoiceTeXprintf (mode, Filename, RechnungsJahr, PrintNummer,
	                         count, mwst1, mwst2, cust->KundenNummer,
	                         Anschrift, zeichen, orddate, 0, 1, bigbuf,
	                         invdate))
	    {
	      BPTR incon;
	      unsigned char commbuff[170];

	      /*
	      **  TeX aufrufen
	      */
	      strcpy (ConWin, TheConWin);
	      if (pubname)
		{
		  strcat (ConWin, "/SCREEN");
		  strcat (ConWin, pubname);
		}

	      incon = Open (ConWin, MODE_OLDFILE);

	      if (incon)
		{
		  DVIprintTags[0].ti_Data = incon;

		  sprintf (commbuff, "%s &%s %s.tex", CO_GetTeXName (),
			   CO_GetFormatName (), Filename);

		  if (!SystemTagList (commbuff, DVIprintTags))
		    {
		      if (justshow)
			{
			  /*
			  **  ShowDVI aufrufen
			  */
			  if (pubname)
			    {
			      sprintf (commbuff, "%s PUB %s %s.dvi",
			               CO_GetPreviewName (),
				       pubname, Filename);
			    }
			  else
			    {
			      sprintf (commbuff, "%s %s.dvi",
			               CO_GetPreviewName (),
				       Filename);
			    }

			  if (!SystemTagList (commbuff, DVIprintTags))
			    {
			      /* nichts ist zu tun, alles hat geklappt */
			    }
			  else
			    result = error = ERR_PRINT_PRINTING;

			}
		      else
			{
			  /*
			  **  DVIprint aufrufen
			  */
			  sprintf (commbuff, "%s HOFFSET=%ldtruemm "
			           "VOFFSET=%ldtruemm "
				   "FROM 1 TO 1000 PRINTER %s UNI off NOLOG "
				   "%s.dvi", CO_GetPrintName (),
				   CO_GetDVIHoffset (), CO_GetDVIVoffset (),
				   CO_GetDVIprinter (), Filename);

			  if (!SystemTagList (commbuff, DVIprintTags))
			    {
			      /* nichts ist zu tun, alles hat geklappt */
			    }
			  else
			    result = error = ERR_PRINT_PRINTING;

			}

		    }
		  else
		    result = error = ERR_PRINT_TEX;
		  Delay (50);
		  Close (incon);
		}
	      else
		{
		  if (incon)
		    Close (incon);
		  result = error = ERR_PRINT_CON;
		}
	    }
	  else
	    result = error = ERR_PRINT_INTERNAL;
	  CurrentDir (olddir);
	  UnLock (newdir);
	}
      else
	result = error = ERR_PRINT_PATH;
    }

  return (result);
}


static void 
BuildLocaleString (STRPTR buffer)
{
  char tmp1[20], tmp2[20], tmp3[20];

  strcpy (tmp1, Locale->loc_MonCS);
  ParseTeXLine (tmp1, 19, FALSE);

  strcpy (tmp2, Locale->loc_MonDecimalPoint);
  ParseTeXLine (tmp2, 19, FALSE);

  strcpy (tmp3, Locale->loc_MonGroupSeparator);
  ParseTeXLine (tmp3, 19, FALSE);

  sprintf (buffer, "\n\\def\\currencyname{%s}%%\n"
	   "\\def\\fracsep{%s}%%\n"
	   "\\def\\millsep{%s}%%\n"
	   "\\def\\thousep{%s}%%\n\n",
	   tmp1, tmp2, tmp3, tmp3);
}

/*
** Ausdruck des Lineals zum Testen der Offsets.
**
** Druckt das DVI-File "texwork/checkprt.dvi" aus.
**
*/

int 
P_PrintTest (STRPTR pubname)
{
  int result;
  BPTR incon;
  unsigned char commbuff[170];
  unsigned char ConWin[120];

  result = error = ERR_PRINT_OK;

  strcpy (ConWin, TheConWin);
  if (pubname)
    {
      strcat (ConWin, "/SCREEN");
      strcat (ConWin, pubname);
    }

  incon = Open (ConWin, MODE_OLDFILE);
  if (incon)
    {
      DVIprintTags[0].ti_Data = incon;

      /*
      **  DVIprint aufrufen
      */

      sprintf (commbuff, "%s HOFFSET=%ldtruemm VOFFSET=%ldtruemm "
	       "FROM 1 TO 1000 PRINTER %s UNI off NOLOG texwork/checkprt.dvi",
	       CO_GetPrintName (), CO_GetDVIHoffset (), CO_GetDVIVoffset (),
	       CO_GetDVIprinter ());

      if (SystemTagList (commbuff, DVIprintTags))
	result = error = ERR_PRINT_PRINTING;

      Delay (50);
      Close (incon);
    }
  else
    {
      if (incon)
	Close (incon);
      result = error = ERR_PRINT_CON;
    }

  return (result);
}


/*
**  Schnittstelle für Invoice.
**
**  Liefert der TeX-Ausgabe den aktuellen Artikel mit allen nötigen
**  Daten aus der eigenen Liste.
*/

int 
invoiceinterface (int Positionsnummer, char *Artikelnummer,
  char *Artikelbezeichnung, double *Einzelpreis, double *Menge,
  int *Preistabelle, char *AppendString)
{
  /*
  ** Überträge hier die Werte aus Rechnungsposition |Positionsnummer|
  ** in die Standardfelder.  Als Rückgabewert wird eine Fehlernummer
  ** erwartet, also $0$, falls die Übertragung geklappt hat, und
  ** ein Wert ungleich $0$ im Fehlerfall.
  */

  struct Article article;
  int error = 0;

  if (!GetArticle (Positionsnummer - 1, &article))
    {
      unsigned char buffer[200];

      strcpy (buffer, article.Bezeichnung);
      ParseTeXLine (buffer, 199, FALSE);

      strcpy (Artikelbezeichnung, buffer);
      *Einzelpreis = article.Betrag;
      *Menge = article.Menge;
      *Preistabelle = article.Preistabelle;

      strcpy (buffer, article.Artikelnummer);
      ParseTeXLine (buffer, 99, FALSE);
      strcpy (Artikelnummer, buffer);

      strcpy (buffer, "0|0|0");
      strcpy (AppendString, buffer);
    }
  else
    error = 1;

  return (error);
}


/****i* BriefWindow/ParseTeXLine ********************************************
*
*   NAME
*	ParseTeXLine -- analysiert jede Textzeile und wandelt sie für TeX
*
*   SYNOPSIS
*	ParseTeXLine( line, len, command );
*
*	void ParseTeXLine( STRPTR, UWORD, BOOL );
*
*   FUNCTION
*	Diese Funktion wird für SaveText() benötigt, um jede Textzeile
*	in eine für TeX lesbare Zeile umzuwandeln. Alle Sonderzeichen
*	werden hiermit in Sequenzen umgewandelt.
*
*   INPUTS
*	line - Zeiger auf den Puffer, in dem die orginale Textzeile steht
*	len  - Länge des Puffers in Byte. Der Puffer ist ein Byte größer
*	       als angegeben, wegen einem abschließendem Nullbyte.
*	command - mit TRUE werden die {x}-Befehle ausgewertet. mit FALSE
*	          werden diese ignoriert
*
*   RESULT
*	keine
*
*   SEE ALSO
*	console/SaveText(), MakeTeXLetter()
*
*****************************************************************************
*
*/

static void 
ParseTeXLine (STRPTR line, UWORD len, BOOL command)
{
  STRPTR StartPtr;
  UWORD endpos;
  STRPTR copyptr;
  BOOL oldparse;

  BOOL bDirectMode = FALSE;

  StartPtr = line;

  while (*StartPtr)
    {
      /* momentane Länge errechnen */
      endpos = strlen (line);

      if (bDirectMode)
	{
	  /* direkte TeX-Eingabe möglich */
	  if (strncmp ("{@}", StartPtr, 3) == 0)
	    {
	      /* TeX-Eingabe abschalten */
	      StartPtr[0] = ' ';
	      StartPtr[1] = ' ';
	      StartPtr[2] = ' ';
	      StartPtr += 2;
	      bDirectMode = FALSE;
	    }

	  StartPtr++;
	  continue;		/* go to next while */
	}

      /* Zeichen analysieren */
      switch ((UBYTE) * StartPtr)
	{
	case '%':
	case '$':
	case '#':
	case '_':
	case '&':
	case '~':
	case '^':
	  /* Umwandlung von 'Z' in '\\Z{}' */
	  if (endpos < len - 2)
	    {
	      /* Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 3) = *copyptr;
		}
	      *(StartPtr + 2) = '{';
	      *(StartPtr + 3) = '}';
	      *(StartPtr + 1) = *StartPtr;
	      *StartPtr = '\\';
	      StartPtr += 3;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case (UBYTE) '¹':
	case (UBYTE) '²':
	case (UBYTE) '³':
	  /* Umwandlung von '¹' in '$^1$' */
	  if (endpos < len - 2)
	    {
	      char c;

	      /* Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 3) = *copyptr;
		}
	      if ((UBYTE) * StartPtr == (UBYTE) '¹')
		c = '1';
	      else if ((UBYTE) * StartPtr == (UBYTE) '²')
		c = '2';
	      else
		c = '3';
	      strncpy (StartPtr, "$^1$", 4);
	      StartPtr[2] = c;
	      StartPtr += 3;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case (UBYTE) '¼':
	case (UBYTE) '½':
	case (UBYTE) '¾':
	  /* Umwandlung von '¼' in '$\frac1/4$' */
	  if (endpos < len - 8)
	    {
	      char a, b;

	      /* Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 9) = *copyptr;
		}
	      if ((UBYTE) * StartPtr == (UBYTE) '¼')
		a = '1', b = '4';
	      else if ((UBYTE) * StartPtr == (UBYTE) '½')
		a = '1', b = '2';
	      else
		a = '3', b = '4';

	      strncpy (StartPtr, "$\\frac1/2$", 10);
	      StartPtr[6] = a;
	      StartPtr[8] = b;
	      StartPtr += 9;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case (UBYTE) '·':
	  /* Umwandlung von '·' in '$\cdot$' */
	  if (endpos < len - 5)
	    {
	      /* Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 6) = *copyptr;
		}
	      strncpy (StartPtr, "$\\cdot$", 7);
	      StartPtr += 6;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case (UBYTE) '°':
	  /* Umwandlung von '°' in '$^\circ$' */
	  if (endpos < len - 6)
	    {
	      /* Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 7) = *copyptr;
		}
	      strncpy (StartPtr, "$^\\circ$", 8);
	      StartPtr += 7;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case (UBYTE) '©':
	  /* Umwandlung von '©' in '\copyright{}' */
	  if (endpos < len - 10)
	    {
	      /* Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 11) = *copyptr;
		}
	      strncpy (StartPtr, "\\copyright{}", 12);
	      StartPtr += 11;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case '\n':
	  if (command)
	    {
	      if (*(StartPtr + 1) == '\n')
		{
		  /* Umwandlung von '\n\n' in '\n\\bigskip\n' */
		  if (endpos < len - 7)
		    {
		      /* Backslash einfügen */
		      for (copyptr = line + endpos; copyptr >= StartPtr;
		           copyptr--)
			{
			  *(copyptr + 8) = *copyptr;
			}
		      strncpy (StartPtr, "\n\\bigskip\n", 10);
		      StartPtr += 8;
		    }
		}
	      else
		{
		  /* Umwandlung von '\n' in '\n\n' */
		  if (endpos < len)
		    {
		      /* Backslash einfügen */
		      for (copyptr = line + endpos; copyptr >= StartPtr;
		           copyptr--)
			{
			  *(copyptr + 1) = *copyptr;
			}
		      *(StartPtr + 1) = '\n';
		      *StartPtr = '\n';
		      StartPtr += 1;
		    }
		}
	    }
	  break;

	  /* { */
	case '}':
	case '{':		/* } */
	  oldparse = TRUE;

	  if (command && *StartPtr == '{')
	    {
	      BOOL checked = FALSE;

	      /* Briefmodus. In den Klammern sind die Befehle */

	      UWORD ilen, iold;
	      STRPTR istr, ifill;
	      char buffer[60];

	      oldparse = FALSE;

	      istr = "   ";
	      switch ((unsigned char) *(StartPtr + 1))
		{
		case '@':
		  bDirectMode = TRUE;	/* TeX-Eingabe ermöglichen */
		  checked = TRUE;
		  istr = "     ";
		  break;

		case ' ':
		  istr = "\\hfill\\ ";
		  checked = TRUE;
		  break;

		case 'b':
		  /* Fettschrift an */
		  if (*(StartPtr + 3) == ' ')
		    istr = "\\bf\\ ";
		  else
		    istr = "\\bf ";
		  checked = TRUE;
		  break;

		case 'd':
		  istr = "\\hskip 0pt\\dotfill\\ ";
		  checked = TRUE;
		  break;

		case 'i':
		  if (*(StartPtr + 3) == ' ')
		    istr = "\\sl\\ ";
		  else
		    istr = "\\sl ";
		  checked = TRUE;
		  break;

		case 'n':
		  if (*(StartPtr + 3) == ' ')
		    istr = "\\rm\\ ";
		  else
		    istr = "\\rm ";
		  checked = TRUE;
		  break;

		}

	      if (!checked)
		{
		  ifill = "\\hfil";
		  switch ((unsigned char) *(StartPtr + 1))
		    {
		    case '.':
		      ifill = "\\dotfill";
		      ilen = atoi (StartPtr + 2);
		      break;
		    case '-':
		      ifill = "\\hrulefill";
		      ilen = atoi (StartPtr + 2);
		      break;
		    default:
		      ifill = "\\hfil";
		      ilen = atoi (StartPtr + 1);
		    }
		  if ((unsigned char) *(StartPtr + 1) == 'm')
		    {
		      sprintf (buffer, "\\specmacro%c", *(StartPtr + 2));
		      istr = buffer;
		      if (*(StartPtr + 3) == ' ')
			strcat (buffer, "\\ ");
		      else
			strcat (buffer, " ");
		      checked = TRUE;
		    }
		  else
		    {
		      if (ilen)
			{
			  sprintf (buffer, "\\hskip 0pt\\hbox to %dcm{%s}",
			           ilen, ifill);
			  istr = buffer;
			  checked = TRUE;
			}
		      else
			istr = " ";
		    }
		}

	      if (!checked)
		{
		  oldparse = TRUE;
		}
	      else
		{
		  ilen = strlen (istr);
		  for (iold = 1; iold < 6 && StartPtr[iold - 1] != '}';
		       iold++);
		  iold++;	/* ja, nach der for-schleife!!! */
		  if (endpos < len - (ilen - iold))
		    {
		      /* Ersatz einfügen */
		      for (copyptr = line + endpos; copyptr >= StartPtr;
		           copyptr--)
			{
			  *(copyptr + ilen - iold + 1) = *copyptr;
			}
		      strncpy (StartPtr, istr, ilen);
		      StartPtr += ilen - 1;
		    }
		  else
		    {
		      /* Zeichen entfernen */
		      strncpy (StartPtr, "   ", 3);
		      StartPtr += 2;
		    }
		}

	    }

	  if (oldparse)
	    {
	      /* alter Modus. Zeichen einfach darstellen */
	      /* Zeichen im Mathemodus */
	      if (endpos < len - 2)
		{
		  /* Backslash einfügen */
		  for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		    {
		      *(copyptr + 3) = *copyptr;
		    }
		  *(StartPtr + 1) = '\\';
		  *(StartPtr + 3) = '$';
		  *(StartPtr + 2) = *StartPtr;
		  *StartPtr = '$';
		  StartPtr += 3;
		}
	      else
		/* Zeichen entfernen */
		*StartPtr = ' ';
	    }
	  break;

	case '|':
	case '<':
	case '>':
	  /* Zeichen im Mathemodus */
	  if (endpos < len - 1)
	    {
	      /* jedoch hier kein Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 2) = *copyptr;
		}
	      *(StartPtr + 2) = '$';
	      *(StartPtr + 1) = *StartPtr;
	      *StartPtr = '$';
	      StartPtr += 2;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case '£':
	  /* Pfund Sterling */
	  if (endpos < len - 5)
	    {
	      /* Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 6) = *copyptr;
		}
	      strncpy (StartPtr, "{\\it\\$}", 7);
	      StartPtr += 6;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case '\\':
	  /* Zeichen im Mathemodus */
	  if (endpos < len - 10)
	    {
	      /* Backslash einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 11) = *copyptr;
		}
	      strncpy (StartPtr, "$\\backslash$", 12);
	      StartPtr += 11;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case '\"':
	  /* Anführungszeichen 'patchen' */
	  if (endpos < len - 1)
	    {
	      /* Anführungszeichen einfügen */
	      for (copyptr = line + endpos; copyptr >= StartPtr; copyptr--)
		{
		  *(copyptr + 2) = *copyptr;
		}
	      strncpy (StartPtr, "\"{}", 3);
	      StartPtr += 2;
	    }
	  else
	    /* Zeichen entfernen */
	    *StartPtr = ' ';
	  break;

	case 0xa0:
	  /* 'hartes' Space ASCII 160 in ein normales Space wandeln */
	  *StartPtr = ' ';
	  break;

	}
      StartPtr++;
    }
}


/*
** Wandle alle Spaces zu "\ts" um
*/

static void 
CompressSpaces (STRPTR line)
{
  unsigned char buffer[100];
  STRPTR p, lastp;

  strcpy (buffer, line);
  lastp = buffer;

  while (p = strchr (lastp, ' '))
    {
      strncpy (line, lastp, p - lastp);
      line += (p - lastp);
      strcpy (line, "\\ts ");
      line += 4;
      lastp = p + 1;
    }
  strcpy (line, lastp);
}

/*
** Erzeugung des Files "texwork/invoice.tex"
*/

extern STRPTR ProgVersion;	/* in MUI-Rechnung.c */

int 
P_SaveConfig (void)
{
  FILE *file;
  int result = ERR_PRINT_SAVE;
  BOOL ok = TRUE;
  unsigned char buf1[100], buf2[100], buf3[100], buf4[100];

  if (file = fopen ("texwork/invoice.tex", "w"))
    {
      strcpy (buf1, CO_GetBankName ());
      ParseTeXLine (buf1, 99, FALSE);

      strcpy (buf2, CO_GetBLZ ());
      ParseTeXLine (buf2, 99, FALSE);
      CompressSpaces (buf2);

      strcpy (buf3, CO_GetKontonr ());
      ParseTeXLine (buf3, 99, FALSE);
      CompressSpaces (buf3);

      /*
      ** erzeuge das File "texwork/invoice.tex"
      **
      ** · Kopf mit Informationen
      */

      if (ok && fprintf (file, "%%\n"
			 "%% This file is machine generated by '%s'\n"
			 "%%\n"
			 "\\input invoicemacro\n",
			 ProgVersion + 7) < 0)
	ok = FALSE;

      /*
      ** · Bankverbindung
      */

      if (strlen (buf1) || strlen (buf2) || strlen (buf3))
	{
	  if (ok && fprintf (file, "\\bankaccount{%s \\BLZ{%s}\\ %s}%%\n",
			     buf1, buf2, buf3) < 0)
	    ok = FALSE;
	}
      else
	{
	  if (ok && fprintf (file, "\\bankaccount{}%%\n") < 0)
	    ok = FALSE;
	}

      /*
      ** · Telefonnummer
      ** · Faxnummer
      */

      strcpy (buf1, CO_GetPhoneVorwahl ());
      ParseTeXLine (buf1, 99, FALSE);
      CompressSpaces (buf1);

      strcpy (buf2, CO_GetPhone ());
      ParseTeXLine (buf2, 99, FALSE);
      CompressSpaces (buf2);

      strcpy (buf3, CO_GetFaxVorwahl ());
      ParseTeXLine (buf3, 99, FALSE);
      CompressSpaces (buf3);

      strcpy (buf4, CO_GetFax ());
      ParseTeXLine (buf4, 99, FALSE);
      CompressSpaces (buf4);

      if (ok && fprintf (file,
                         "\\phonenumber{\\pushup{(}%s\\pushup{)} %s}%%\n",
			 buf1, buf2) < 0)
	ok = FALSE;

      if (strlen (buf3) && strlen (buf4))
	{
	  if (ok && fprintf (file,
	                     "\\faxnumber{\\pushup{(}%s\\pushup{)} %s}%%\n",
			     buf3, buf4) < 0)
	    ok = FALSE;
	}
      else
	{
	  if (ok && fprintf (file, "\\faxnumber{}%%\n") < 0)
	    ok = FALSE;
	}

      /*
      ** · Unsere Zeichen
      */

      strcpy (buf1, CO_GetZeichen ());
      ParseTeXLine (buf1, 99, FALSE);

      if (ok && fprintf (file, "\\myref{%s}%%\n", buf1) < 0)
	ok = FALSE;

      /*
      ** · Firmenname
      ** · Straße
      ** · Ort
      ** · Inhaber
      */

      strcpy (buf1, CO_GetFirma ());
      ParseTeXLine (buf1, 99, FALSE);

      strcpy (buf2, CO_GetStrasse ());
      ParseTeXLine (buf2, 99, FALSE);

      strcpy (buf3, CO_GetOrt ());
      ParseTeXLine (buf3, 99, FALSE);

      strcpy (buf4, CO_GetInhaber ());
      ParseTeXLine (buf4, 99, FALSE);

      if (ok && fprintf (file, "\\company{%s}%%\n"
			 "\\street{%s}%%\n"
			 "\\city{%s}%%\n"
			 "\\owner{%s}%%\n",
			 buf1, buf2, buf3, buf4) < 0)
	ok = FALSE;

      /*
      ** · zwei Kopfzeilen
      */

      strcpy (buf1, CO_GetKopf1 ());
      ParseTeXLine (buf1, 99, FALSE);

      strcpy (buf2, CO_GetKopf2 ());
      ParseTeXLine (buf2, 99, FALSE);

      if (ok && fprintf (file, "\n\\def\\companytext{%s\\par %s}\n",
			 buf1, buf2) < 0)
	ok = FALSE;

      /*
      ** · vier Fußzeilen
      */

      strcpy (buf1, CO_GetFuss1 ());
      ParseTeXLine (buf1, 99, FALSE);

      strcpy (buf2, CO_GetFuss2 ());
      ParseTeXLine (buf2, 99, FALSE);

      strcpy (buf3, CO_GetFuss3 ());
      ParseTeXLine (buf3, 99, FALSE);

      strcpy (buf4, CO_GetFuss4 ());
      ParseTeXLine (buf4, 99, FALSE);

      if (ok && fprintf (file, "\n\\setthanksname{\\centerline{%s}\n"
			 "\\centerline{%s}\n"
			 "\\centerline{%s}\n"
			 "\\centerline{%s}}\n",
			 buf1, buf2, buf3, buf4) < 0)
	ok = FALSE;

      /*
      ** · Anpassung an das Formular für Manni
      */

      if (ok && fprintf (file, "\n%% patch the bodyhead\n\n"
			 "\\input invoicepatch\n"
	  ) < 0)
	ok = FALSE;

      if (ok)
	result = ERR_PRINT_OK;


      fclose (file);
    }
  return (error = result);
}


/*
** Drucke ein Etikett aus ( die Größe ist momentan 6cm x 3.6cm )
** Die Etiketten beginnen 7mm vom linken und 16mm vom oberen Rand.
** Die Breite ist 66mm und die Höhe 38mm (laut Rechenformeln unten).
** Die Breite ist 63.5mm und die Höhe 38.1mm (laut AmigaGuide).
**
**
** 2.12.94: 18.12.94 -> LF_BIGLABEL im Keyfile
** wenn das Define BIGLABEL gesetzt ist, dann werden Etiketten der Größe
** 70mmx37mm erzeugt. Oberer und unterer Rand = 0mm, linker und rechter Rand
** ist 1mm.
**
** Parameter:
**
** pubname    - Name des Public Screen oder NULL
** col        - Spalte auf dem Blatt  (1..3)
** line       - Zeile auf dem Blatt   (1..7)
** s1...s5    - 5 Zeilen für Anschrift
*/

int 
P_PrintLabel (STRPTR pubname, UWORD col, UWORD line, STRPTR s1,
	      STRPTR s2, STRPTR s3, STRPTR s4, STRPTR s5)
{
  int result;
  BPTR incon;
  unsigned char commbuff[170];
  unsigned char ConWin[120];
  BPTR newdir, olddir;
  FILE *file;
  BOOL ok = TRUE;
  unsigned char buf1[MAX_PRINT_LEN], buf2[MAX_PRINT_LEN], buf3[MAX_PRINT_LEN];
  LONG ret;
  unsigned char *pcLandscape;

  result = error = ERR_PRINT_OK;

  if (newdir = Lock ("texwork", ACCESS_READ))
    {
      olddir = CurrentDir (newdir);

      strcpy (ConWin, TheConWin);
      if (pubname)
	{
	  strcat (ConWin, "/SCREEN");
	  strcat (ConWin, pubname);
	}

      if (file = fopen ("Etikett.tex", "w"))
	{
	  /* Fonts definieren */
	  if (fprintf (file, "\\input labelmacro\n") < 0)
	    ok = FALSE;

	  /* Etikettgröße und Offsets */

	  if (ok && fprintf (file, "\\labelposition|%d|%d|%%\n",
			     col, line) < 0)
	    ok = FALSE;

	  /* Absender in klein */
	  strcpy (buf1, CO_GetFirma ());
	  ParseTeXLine (buf1, MAX_PRINT_LEN - 1, FALSE);

	  strcpy (buf2, CO_GetStrasse ());
	  ParseTeXLine (buf2, MAX_PRINT_LEN - 1, FALSE);

	  strcpy (buf3, CO_GetOrt ());
	  ParseTeXLine (buf3, MAX_PRINT_LEN - 1, FALSE);
	  if (ok && fprintf (file, "\\def\\ownfirm{%s}\n"
			     "\\def\\ownstreet{%s}\n"
			     "\\def\\owncity{%s}\n",
			     buf1, buf2, buf3) < 0)
	    ok = FALSE;


	  /* Adresse */
	  if (ok && fprintf (file, "\\beginlabel\n") < 0)
	    ok = FALSE;

	  strcpy (buf1, s1);
	  ParseTeXLine (buf1, MAX_PRINT_LEN - 1, FALSE);
	  if (ok && fprintf (file, "%s\n", buf1) < 0)
	    ok = FALSE;

	  strcpy (buf1, s2);
	  ParseTeXLine (buf1, MAX_PRINT_LEN - 1, FALSE);
	  if (ok && fprintf (file, "%s\n", buf1) < 0)
	    ok = FALSE;

	  strcpy (buf1, s3);
	  ParseTeXLine (buf1, MAX_PRINT_LEN - 1, FALSE);
	  if (ok && fprintf (file, "%s\n", buf1) < 0)
	    ok = FALSE;

	  strcpy (buf1, s4);
	  ParseTeXLine (buf1, MAX_PRINT_LEN - 1, FALSE);
	  if (ok && fprintf (file, "%s\n", buf1) < 0)
	    ok = FALSE;

	  strcpy (buf1, s5);
	  ParseTeXLine (buf1, MAX_PRINT_LEN - 1, FALSE);
	  if (ok && fprintf (file, "%s\n", buf1) < 0)
	    ok = FALSE;

	  if (ok && fprintf (file, "\\endlabel\n") < 0)
	    ok = FALSE;

	  if (ok && fprintf (file, "\\bye\n") < 0)
	    ok = FALSE;

	  if (!ok)
	    result = error = ERR_PRINT_SAVE;

	  fclose (file);
	}
      else
	result = error = ERR_PRINT_SAVE;


      if (!result)
	{
	  incon = Open (ConWin, MODE_OLDFILE);

	  if (incon)
	    {
	      DVIprintTags[0].ti_Data = incon;

	      sprintf (commbuff, "%s &%s Etikett.tex", CO_GetTeXName (),
	               CO_GetFormatName ());

	      ret = SystemTagList (commbuff, DVIprintTags);
	      if (ret >= 0 && ret < 20)
		{
		  /*
		  **  DVIprint aufrufen
		  */

		  if (CO_LabelLandscape ())
		    {
		      pcLandscape = "LAND";
		    }
		  else
		    {
		      pcLandscape = "";
		    }

		  sprintf (commbuff, "%s HOFFSET=%ldtruemm VOFFSET=%ldtruemm "
			   "FROM 1 TO 1000 PRINTER %s %s UNI off "
			   "NOLOG Etikett.dvi", CO_GetPrintName (),
			   CO_GetDVIHoffset (), CO_GetDVIVoffset (),
			   CO_GetDVIprinter (), pcLandscape);

		  if (!SystemTagList (commbuff, DVIprintTags))
		    {
		      /* alles ok, nichts mehr machen... */
		    }
		  else
		    result = error = ERR_PRINT_PRINTING;

		}
	      else
		result = error = ERR_PRINT_PRINTING;

	      Delay (50);
	      Close (incon);
	    }
	  else
	    {
	      if (incon)
		Close (incon);
	      else
		result = error = ERR_PRINT_CON;
	    }
	}
      CurrentDir (olddir);
      UnLock (newdir);
    }

  return (result);
}


/*
** Drucke eine Visitenkarte (Etikett) aus ( momentan 6cm x 3.6cm )
**
** Parameter:
**
** pubname    - Name des Public Screen oder NULL
** col        - Spalte auf dem Blatt  (1..3)
** line       - Zeile auf dem Blatt   (1..7)
*/

int 
P_PrintVisit (STRPTR pubname, UWORD col, UWORD line)
{
  int result;
  BPTR incon;
  unsigned char commbuff[170];
  unsigned char ConWin[120];
  BPTR newdir, olddir;
  FILE *file;
  BOOL ok = TRUE;
/*   unsigned char plz[MAX_PRINT_LEN]; */
  unsigned char buf1[MAX_PRINT_LEN], buf2[MAX_PRINT_LEN], buf3[MAX_PRINT_LEN];
/*   STRPTR ort; */
  LONG ret;

  result = error = ERR_PRINT_OK;

  if (newdir = Lock ("texwork", ACCESS_READ))
    {
      olddir = CurrentDir (newdir);

      strcpy (ConWin, TheConWin);
      if (pubname)
	{
	  strcat (ConWin, "/SCREEN");
	  strcat (ConWin, pubname);
	}

      if (file = fopen ("Visitenkarte.tex", "w"))
	{
	  if (fprintf (file, "\\input labelmacro\n") < 0)
	    ok = FALSE;

	  /* Etikettgröße und Offsets */
	  if (ok && fprintf (file, "\\visitposition|%d|%d|%%\n\n",
			     col, line) < 0)
	    ok = FALSE;

	  /* Kopf mit Firmenschrift und den zwei Kopfzeilen */
	  strcpy (buf1, CO_GetFirma ());
	  ParseTeXLine (buf1, MAX_PRINT_LEN - 1, FALSE);

	  strcpy (buf2, CO_GetKopf1 ());
	  ParseTeXLine (buf2, MAX_PRINT_LEN - 1, FALSE);

	  strcpy (buf3, CO_GetKopf2 ());
	  ParseTeXLine (buf3, MAX_PRINT_LEN - 1, FALSE);

	  if (ok && fprintf (file, "\\def\\ownfirm{%s}\n"
			     "\\def\\ownheadone{%s}\n"
			     "\\def\\ownheadtwo{%s}\n",
			     buf1, buf2, buf3) < 0)
	    ok = FALSE;

	  /* Adresse unserer Firma */
	  strcpy (buf1, CO_GetInhaber ());
	  ParseTeXLine (buf1, MAX_PRINT_LEN - 1, FALSE);

	  strcpy (buf2, CO_GetStrasse ());
	  ParseTeXLine (buf2, MAX_PRINT_LEN - 1, FALSE);

	  strcpy (buf3, CO_GetOrt ());
	  ParseTeXLine (buf3, MAX_PRINT_LEN - 1, FALSE);
	  if (ok && fprintf (file, "\\def\\ownname{%s}\n"
			     "\\def\\ownstreet{%s}\n"
			     "\\def\\owncity{%s}\n",
			     buf1, buf2, buf3) < 0)
	    ok = FALSE;

	  /* Telefon- und Faxnummer */
	  strcpy (buf1, CO_GetPhoneVorwahl ());
	  ParseTeXLine (buf1, 99, FALSE);
	  CompressSpaces (buf1);

	  strcpy (buf2, CO_GetPhone ());
	  ParseTeXLine (buf2, 99, FALSE);
	  CompressSpaces (buf2);

	  strcpy (buf3, CO_GetFax ());
	  ParseTeXLine (buf3, 99, FALSE);
	  CompressSpaces (buf3);

	  if (ok && fprintf (file, "\\def\\owndialcode{%s}\n"
			     "\\def\\ownphone{%s}\n"
			     "\\def\\ownfax{%s}\n\n"
			     "\\makevisit\n"
			     "\\end\n",
			     buf1, buf2, buf3) < 0)
	    ok = FALSE;

	  if (!ok)
	    result = error = ERR_PRINT_SAVE;

	  fclose (file);
	}
      else
	result = error = ERR_PRINT_SAVE;

      if (!result)
	{
	  incon = Open (ConWin, MODE_OLDFILE);
	  if (incon)
	    {

	      DVIprintTags[0].ti_Data = incon;

	      sprintf (commbuff, "%s &%s Visitenkarte.tex", CO_GetTeXName (),
	               CO_GetFormatName ());

	      ret = SystemTagList (commbuff, DVIprintTags);
	      if (ret >= 0 && ret < 20)
		{
		  /*
		  **  DVIprint aufrufen
		  */

		  sprintf (commbuff, "%s HOFFSET=%ldtruemm VOFFSET=%ldtruemm "
			   "FROM 1 TO 1000 PRINTER %s UNI off NOLOG "
			   "Visitenkarte.dvi", CO_GetPrintName (),
			   CO_GetDVIHoffset (), CO_GetDVIVoffset (),
			   CO_GetDVIprinter ());

		  if (!SystemTagList (commbuff, DVIprintTags))
		    {
		      /* alles ok, nichts mehr machen... */
		    }
		  else
		    result = error = ERR_PRINT_PRINTING;

		}
	      else
		result = error = ERR_PRINT_PRINTING;

	      Delay (50);
	      Close (incon);
	    }
	  else
	    {
	      if (incon)
		Close (incon);
	      result = error = ERR_PRINT_CON;
	    }
	}
      CurrentDir (olddir);
      UnLock (newdir);
    }

  return (result);
}



/*
** Drucke den geladenen Brief aus. Startet DVIprint und TeX
**
** Parameter:
**
**   pubname  - Name des Public Screen oder NULL
**   cust     - Zeiger auf den Kunden
**   number   - Nummer des Briefes
**   letdate  - Datum des Briefs
**   refdate  - Datum für "Ihr Schreiben vom"
**   str      - Inhalt als Text
**   justshow - TRUE wenn ShowDVI laufen soll, FALSE wenn DVIprint laufen soll
*/

int 
P_PrintLetter (STRPTR pubname,
	       struct MinCustomer *cust, STRPTR number,
	       STRPTR letdate, STRPTR refdate, STRPTR str, BOOL justshow)
{
  int result;
  BPTR incon;
  unsigned char commbuff[170];
  unsigned char ConWin[120];
  BPTR newdir, olddir, test;
  FILE *file;
  BOOL ok = TRUE;
  unsigned char Anschrift[5 * MAX_PRINT_LEN];
  LONG ret;
  char datestr[10];
  char buf1[20], toname[100];
  STRPTR buffer;
  char bigbuf[200];
  STRPTR Filename;

  result = error = ERR_PRINT_OK;

  if (buffer = calloc (MAX_LETTER_LEN, 1))
    {
      if (test = Lock ("texwork/invoice.tex", ACCESS_READ))
	{
	  /* file does exist */
	  UnLock (test);
	}
      else
	{
	  /* file does not exist, create it */
	  P_SaveConfig ();
	}

      if (newdir = Lock ("texwork", ACCESS_READ))
	{
	  olddir = CurrentDir (newdir);

	  strcpy (ConWin, TheConWin);
	  if (pubname)
	    {
	      strcat (ConWin, "/SCREEN");
	      strcat (ConWin, pubname);
	    }
	  if (justshow)
	    Filename = "showbrief";
	  else
	    Filename = "printbrief";
	  sprintf (bigbuf, "%s.tex", Filename);

	  if (file = fopen (bigbuf, "w"))
	    {
	      /* Invoicemacros laden */
	      if (fprintf (file, "\\input invoice\n"
			   "\\selectlanguage{german}\n"
			   "\n") < 0)
		ok = FALSE;

	      /* 17.11.94: Spracheinstellungen per Programm speichern */
	      BuildLocaleString (bigbuf);
	      if (fprintf (file, "%s", bigbuf) < 0)
		ok = FALSE;

	      /* Adreßmacro einfügen */
	      sprintf (Anschrift, "%s\n%s\n%s\n%s\n%s\n", cust->Adresse1,
		       cust->Adresse2, cust->Adresse3, cust->Adresse4,
		       cust->Adresse5);
	      ParseTeXLine (Anschrift, 5 * MAX_PRINT_LEN - 1, FALSE);

	      strcpy (toname, cust->Adresse2);
	      ParseTeXLine (toname, 99, FALSE);

	      /*
	      ** falls Briefdatum vorhanden, dann dieses verwenden
	      */

	      datestr[0] = 0;
	      if (strlen (letdate))
		{
		  datestr[0] = letdate[0];
		  datestr[1] = letdate[1];
		  datestr[2] = letdate[3];
		  datestr[3] = letdate[4];
		  datestr[4] = letdate[6];
		  datestr[5] = letdate[7];
		  datestr[6] = letdate[8];
		  datestr[7] = letdate[9];
		  datestr[8] = 0;

		  if (fprintf (file, "\\date{\\printformatteddate{%s}}\n",
			       datestr) < 0)
		    ok = FALSE;
		}

	      /* 
	      ** prüfen, ob mit oder ohne Anschrift gesetzt werden soll.
	      */

	      if (strlen (Anschrift) <= 5)
		{
		  /* es soll ohne Anschrift gesetzt werden. Dann müssen auch
		  ** hier ein paar Sachen eingefügt werden (unlogisch? wieso,
		  ** es gibt ja auch negative Zahlen :-)
		  */

		  if (fprintf (file, "\n%% patch address field\n\n"
			       "\\chardef\\atcode=\\catcode`\\@\n"
			       "\\catcode`\\@=11 %% \\makeatletter\n"
			     "\\def\\address{\\beginlinemode\\getaddress}\n"
			       "{\\obeylines\\gdef\\getaddress #1\n"
			       "  #2\n"
			       "  {#1\\gdef\\addressee{#2}%%\n"
			       "    \\global\\setbox\\theaddress=\\vbox to 0.5cm\\bgroup\\vss\\raggedright%%\n"
			       "    \\hsize=\\longindentation \\everypar{\\hangindent2em}#2\n"
			       "    \\def\\endmode{\\vss\\egroup\\endgroup \\copy\\theaddress \\bigskip\\bigskip}}}\n"
		    "\\catcode`\\@=\\atcode %% return to previous catcode\n"
			       "\n"
			       "\\begintext\n\n"
			       "\\toname{%s}\n"
			       "\\textbody\n"
			       "\\parskip 0pt plus 1pt\n\n",
			       toname ) < 0)
		    ok = FALSE;

		  /*
		  ** · Unsere Zeichen leeren
		  */

		  if (fprintf (file, "\\myref{}\n") < 0)
		    ok = FALSE;
		}
	      else
		{
		  /* es ist also eine Anschrift da, dann alle Zusatzinfos
		  ** mit ausgeben.
		  */

		  if (fprintf (file, "\\begintext\n\n"
			       "\\address\n"
			       "%s\n\n"
			       "\\toname{%s}\n"
			       "\\textbody\n"
			       "\\parskip 0pt plus 1pt\n\n",
			       Anschrift, toname) < 0)
		    ok = FALSE;

		  /* evtl. die Kundennummer setzen */

		  if (cust->KundenNummer)
		    {
		      /*
		      ** · Kundennummer
		      */

		      if (fprintf (file, "\\customernumber=%d\n",
				   cust->KundenNummer) < 0)
			ok = FALSE;
		    }

		  /* weitere Daten setzen */
		  datestr[0] = 0;
		  if (strlen (refdate))
		    {
		      datestr[0] = refdate[0];
		      datestr[1] = refdate[1];
		      datestr[2] = refdate[3];
		      datestr[3] = refdate[4];
		      datestr[4] = refdate[6];
		      datestr[5] = refdate[7];
		      datestr[6] = refdate[8];
		      datestr[7] = refdate[9];
		      datestr[8] = 0;

		      /*
		      ** · Ihr Schreiben vom
		      */

		      if (fprintf (file, "\\orderdate{%s}\n",
				   datestr, buf1) < 0)
			ok = FALSE;
		    }

		  strcpy (buf1, cust->Zeichen);
		  ParseTeXLine (buf1, 19, FALSE);

		  /*
		  ** · Ihre Zeichen
		  */

		  if (fprintf (file, "\\yourref{%s}\n"
			       "\\texthead\n\n",
			       buf1) < 0)
		    ok = FALSE;
		}

	      /*
	      ** jetzt noch alle Einträge ins File schreiben
	      */

	      /* einen Absatz als Fließtext setzen */

	      strcpy (buffer, str);
	      ParseTeXLine (buffer, MAX_LETTER_LEN - 1, TRUE);

	      if (fprintf (file, "\n%s\n\n", buffer) < 0)
		ok = FALSE;


/*
** weitere Befehle
**
** \closing       Gruß \n leerzeile \n Name
** \annotations   Anlagen\n ...
** \ps            ps
*/

	      if (ok && fprintf (file, "\\endtext\n"
				 "\\bye\n") < 0)
		ok = FALSE;

	      if (!ok)
		result = error = ERR_PRINT_SAVE;

	      fclose (file);
	    }
	  else
	    result = error = ERR_PRINT_SAVE;

	  if (!result)
	    {
	      incon = Open (ConWin, MODE_OLDFILE);
	      if (incon)
		{

		  DVIprintTags[0].ti_Data = incon;

		  sprintf (commbuff, "%s &%s %s.tex", CO_GetTeXName (),
		           CO_GetFormatName (), Filename);

		  ret = SystemTagList (commbuff, DVIprintTags);
		  if (ret >= 0 && ret < 20)
		    {
		      if (justshow)
			{
			  /*
			  **  ShowDVI aufrufen
			  */
			  if (pubname)
			    {
			      sprintf (commbuff, "%s PUB %s %s.dvi",
			               CO_GetPreviewName (),
				       pubname, Filename);
			    }
			  else
			    {
			      sprintf (commbuff, "%s %s.dvi",
			               CO_GetPreviewName (), Filename);
			    }

			  if (!SystemTagList (commbuff, DVIprintTags))
			    {
			      /* nichts ist zu tun, alles hat geklappt */
			    }
			  else
			    result = error = ERR_PRINT_PRINTING;

			}
		      else
			{
			  /*
			  **  DVIprint aufrufen
			  */
			  sprintf (commbuff, "%s HOFFSET=%ldtruemm "
			           "VOFFSET=%ldtruemm FROM 1 TO 1000 "
			           "PRINTER %s UNI off NOLOG %s.dvi",
			           CO_GetPrintName (), CO_GetDVIHoffset (),
			           CO_GetDVIVoffset (), CO_GetDVIprinter (),
			           Filename);

			  if (!SystemTagList (commbuff, DVIprintTags))
			    {
			      /* nichts ist zu tun, alles hat geklappt */
			    }
			  else
			    result = error = ERR_PRINT_PRINTING;

			}

		    }
		  else
		    result = error = ERR_PRINT_PRINTING;

		  Delay (50);
		  Close (incon);
		}
	      else
		{
		  if (incon)
		    Close (incon);
		  result = error = ERR_PRINT_CON;
		}
	    }
	  CurrentDir (olddir);
	  UnLock (newdir);
	}
    }
  else
    result = ERR_PRINT_SAVE;	/* eigentlich NOMEM !! */

  return (result);
}



/*
** Hole Fehlerstring ab
*/

STRPTR 
P_GetErrorMsg (void)
{
  return (errormsg[error]);
}


/*
** Ausdruck der Adreßliste, je nach Modus und Listart
**
** mode: 0 = alle Kategorien
**       1 = aktuelle Kategorie
**
** list: 0 = Telefonliste
**       1 = Faxliste
**       2 = Adreßliste
**
** str:  Name der aktuellen Kategorie
*/

int 
P_PrintCust (ULONG mode, ULONG list, STRPTR str, STRPTR pubname)
{
  BPTR newdir, olddir;
  FILE *file;
  BOOL ok = TRUE;
  BPTR incon;
  unsigned char commbuff[170];
  unsigned char ConWin[120];
  LONG ret;
  int result;
  int i;

  STRPTR headline;

  result = error = ERR_PRINT_OK;

  if (newdir = Lock ("texwork", ACCESS_READ))
    {
      olddir = CurrentDir (newdir);


      strcpy (ConWin, TheConWin);
      if (pubname)
	{
	  strcat (ConWin, "/SCREEN");
	  strcat (ConWin, pubname);
	}

      if (file = fopen ("Adressen.tex", "w"))
	{
	  /* Fonts definieren */
	  if (fprintf (file, "\\input listmacro\n") < 0)
	    ok = FALSE;

	  switch (list)
	    {
	    case 1:		/* Faxliste */
	      headline = "Faxliste";
	      break;
	    case 2:		/* Adreßliste */
	      headline = "Adreßliste";
	      break;
	    default:
	    case 0:		/* Telefonliste */
	      headline = "Telefonliste";
	      break;
	    }
	  if (ok && fprintf (file, "\\headline=\\custheadline\n"
	                     "\\def\\headname{%s}\n", headline) < 0)
	    ok = FALSE;

	  if (mode == 0)
	    {
	      /* alle Kategorien ausgeben */
	      for (i = 0; ok && i < C_GetCategoryCount (); i++)
		{
		  C_GetCategory (i, commbuff);
		  ok = printCustCategory (commbuff, mode, list, file);
		}
	    }
	  else
	    {
	      /* nur aktuelle Kategorien ausgeben */

	      if (ok)
		ok = printCustCategory (str, mode, list, file);

	    }
	  if (ok && fprintf (file, "\\bye\n") < 0)
	    ok = FALSE;

	  if (!ok)
	    result = error = ERR_PRINT_SAVE;

	  fclose (file);
	}
      else
	result = error = ERR_PRINT_SAVE;

      if (!result)
	{
	  incon = Open (ConWin, MODE_OLDFILE);
	  if (incon)
	    {

	      DVIprintTags[0].ti_Data = incon;

	      sprintf (commbuff, "%s &%s Adressen.tex", CO_GetTeXName (),
	               CO_GetFormatName ());

	      ret = SystemTagList (commbuff, DVIprintTags);
	      if (ret >= 0 && ret < 20)
		{
		  /*
		  **  DVIprint aufrufen
		  */

		  sprintf (commbuff, "%s HOFFSET=%ldtruemm VOFFSET=%ldtruemm "
			   "FROM 1 TO 1000 PRINTER %s UNI off NOLOG "
			   "Adressen.dvi", CO_GetPrintName (),
			   CO_GetDVIHoffset (), CO_GetDVIVoffset (),
			   CO_GetDVIprinter ());

		  if (!SystemTagList (commbuff, DVIprintTags))
		    {
		      /* alles ok, nichts mehr machen... */
		    }
		  else
		    result = error = ERR_PRINT_PRINTING;

		}
	      else
		result = error = ERR_PRINT_PRINTING;

	      Delay (50);
	      Close (incon);
	    }
	  else
	    {
	      if (incon)
		Close (incon);
	      result = error = ERR_PRINT_CON;
	    }
	}

      CurrentDir (olddir);
      UnLock (newdir);
    }
  else
    result = error = ERR_PRINT_PATH;

  return (result);
}


/*
** Ausdruck einer Rechnungsliste
**
** mode: 0 - Rechnungsliste, 1 - Auftragsliste
*/

int 
P_PrintList (ULONG mode, STRPTR pubname)
{
  BPTR newdir, olddir;
  FILE *file;
  BOOL ok = TRUE;
  BPTR incon;
  unsigned char commbuff[170];
  unsigned char ConWin[120];
  LONG ret;
  int result;
  int i;

  STRPTR headline;

  result = error = ERR_PRINT_OK;

  if (newdir = Lock ("texwork", ACCESS_READ))
    {
      olddir = CurrentDir (newdir);


      strcpy (ConWin, TheConWin);
      if (pubname)
	{
	  strcat (ConWin, "/SCREEN");
	  strcat (ConWin, pubname);
	}

      if (file = fopen ("liste.tex", "w"))
	{
	  /* Fonts definieren */
	  if (fprintf (file, "\\input listmacro\n") < 0)
	    ok = FALSE;

	  switch (mode)
	    {
	    case 1:		/* Auftragsliste */
	      headline = "Auftragsliste";
	      break;
	    default:
	    case 0:		/* Rechnungsliste */
	      headline = "Rechnungsliste";
	      break;
	    }
	  if (ok && fprintf (file, "\\headline=\\invheadline\n"
	                     "\\def\\headname{%s}\n", headline) < 0)
	    ok = FALSE;

	  if (mode == 0)
	    {
	      struct MinInvoice inv;
	      char buf0[60], buf1[30], buf2[30];
	      float sum = 0.0;

	      /* alle Rechnungsinfos ausgeben */
	      for (i = 0; ok && i < IL_GetInvoiceCount (); i++)
		{
		  IL_GetInvoice (i, &inv);

		  strcpy (buf0, inv.Kunde);
		  ParseTeXLine (buf0, 59, FALSE);

		  DisplayBetrag (buf1, inv.sum, 0.0, 0);
		  DisplayBetrag (buf2, inv.payment, 0.0, 0);

		  if (ok && fprintf (file,
		                 "\\invitem|%s|%04d/%d|%s|%s|%s|0|0|0|0|%%\n",
		                 buf0, inv.invoiceYear, inv.invoiceNumber,
		                 inv.invoiceDate, buf1, buf2) < 0)
		    ok = FALSE;

		  sum += inv.sum;
		}

	      DisplayBetrag (buf1, sum, 0.0, 0);
	      if (ok && fprintf (file, "\\sumlist|%s|%%\n", buf1) < 0)
		ok = FALSE;
	    }
	  else if (mode == 1)
	    {
	    }

	  if (ok && fprintf (file, "\\bye\n") < 0)
	    ok = FALSE;

	  if (!ok)
	    result = error = ERR_PRINT_SAVE;

	  fclose (file);
	}
      else
	result = error = ERR_PRINT_SAVE;

      if (!result)
	{
	  incon = Open (ConWin, MODE_OLDFILE);
	  if (incon)
	    {

	      DVIprintTags[0].ti_Data = incon;

	      sprintf (commbuff, "%s &%s liste.tex", CO_GetTeXName (),
	               CO_GetFormatName ());

	      ret = SystemTagList (commbuff, DVIprintTags);
	      if (ret >= 0 && ret < 20)
		{
		  /*
		  **  DVIprint aufrufen
		  */

		  sprintf (commbuff, "%s HOFFSET=%ldtruemm VOFFSET=%ldtruemm "
			   "FROM 1 TO 1000 PRINTER %s UNI off NOLOG liste.dvi", CO_GetPrintName (),
			   CO_GetDVIHoffset (), CO_GetDVIVoffset (),
			   CO_GetDVIprinter ());

		  if (!SystemTagList (commbuff, DVIprintTags))
		    {
		      /* alles ok, nichts mehr machen... */
		    }
		  else
		    result = error = ERR_PRINT_PRINTING;

		}
	      else
		result = error = ERR_PRINT_PRINTING;

	      Delay (50);
	      Close (incon);
	    }
	  else
	    {
	      if (incon)
		Close (incon);
	      result = error = ERR_PRINT_CON;
	    }
	}

      CurrentDir (olddir);
      UnLock (newdir);
    }
  else
    result = error = ERR_PRINT_PATH;

  return (result);
}


/*
** Ausgabe einer Kundenkategorie
*/

static BOOL 
printCustCategory (STRPTR category, ULONG mode, ULONG list, FILE * file)
{
  BOOL ok = TRUE;
  struct Customer cust;
  int i;
  char buf1[200], buf2[100];

  /* überschrift ausgeben */
  strcpy (buf1, category);
  ParseTeXLine (buf1, 199, FALSE);
  if (ok && fprintf (file, "\\category|%s|%%\n", buf1) < 0)
    ok = FALSE;

  for (i = 0; ok && i < C_GetCustomerCount (); i++)
    {
      C_GetCustomer (i, &cust);
      if (!stricmp (category, cust.Kategorie))
	{
	  switch (list)
	    {
	    case 1:		/* Faxliste */
	      if (strlen (cust.Fax))
		{
		  C_PrintCustLine ((struct MinCustomer *) &cust, buf1);
		  ParseTeXLine (buf1, 199, FALSE);

		  strcpy (buf2, cust.Fax);
		  ParseTeXLine (buf2, 99, FALSE);

		  if (ok && fprintf (file, "\\phoneline|%s|%s|%%\n",
				     buf1, buf2) < 0)
		    ok = FALSE;
		}
	      break;
	    case 2:		/* Adreßliste */
	      if (ok && fprintf (file, "\\addressfield|") < 0)
		ok = FALSE;

	      strcpy (buf1, cust.Adresse1);
	      ParseTeXLine (buf1, 199, FALSE);
	      if (ok && fprintf (file, "%s|", buf1) < 0)
		ok = FALSE;

	      strcpy (buf1, cust.Adresse2);
	      ParseTeXLine (buf1, 199, FALSE);
	      if (ok && fprintf (file, "%s|", buf1) < 0)
		ok = FALSE;

	      strcpy (buf1, cust.Adresse3);
	      ParseTeXLine (buf1, 199, FALSE);
	      if (ok && fprintf (file, "%s|", buf1) < 0)
		ok = FALSE;

	      strcpy (buf1, cust.Adresse4);
	      ParseTeXLine (buf1, 199, FALSE);
	      if (ok && fprintf (file, "%s|", buf1) < 0)
		ok = FALSE;

	      strcpy (buf1, cust.Adresse5);
	      ParseTeXLine (buf1, 199, FALSE);
	      if (ok && fprintf (file, "%s|", buf1) < 0)
		ok = FALSE;

	      if (ok && fprintf (file, "%d|", cust.KundenNummer) < 0)
		ok = FALSE;

	      strcpy (buf1, cust.Telefon);
	      ParseTeXLine (buf1, 199, FALSE);
	      if (ok && fprintf (file, "%s|", buf1) < 0)
		ok = FALSE;

	      strcpy (buf1, cust.Fax);
	      ParseTeXLine (buf1, 199, FALSE);
	      if (ok && fprintf (file, "%s|%%\n", buf1) < 0)
		ok = FALSE;

	      break;

	    default:
	    case 0:		/* Telefonliste */
	      if (strlen (cust.Telefon))
		{
		  C_PrintCustLine ((struct MinCustomer *) &cust, buf1);
		  ParseTeXLine (buf1, 199, FALSE);

		  strcpy (buf2, cust.Telefon);
		  ParseTeXLine (buf2, 99, FALSE);

		  if (ok && fprintf (file, "\\phoneline|%s|%s|%%\n",
				     buf1, buf2) < 0)
		    ok = FALSE;

		}
	      break;
	    }

	}
    }
  return (ok);
}

/*
** Ausdruck der Artikelliste, je nach Modus
**
** mode: 0 = alle Kategorien
**       1 = aktuelle Kategorie
**
** str: Name der aktuellen Kategorie
*/

int 
P_PrintArticle (ULONG mode, STRPTR str, STRPTR pubname)
{
  BPTR newdir, olddir;
  FILE *file;
  BOOL ok = TRUE;
  BPTR incon;
  unsigned char commbuff[170];
  unsigned char ConWin[120];
  LONG ret;
  int result;
  int i;

  result = error = ERR_PRINT_OK;

  if (newdir = Lock ("texwork", ACCESS_READ))
    {
      olddir = CurrentDir (newdir);

      strcpy (ConWin, TheConWin);
      if (pubname)
	{
	  strcat (ConWin, "/SCREEN");
	  strcat (ConWin, pubname);
	}

      if (file = fopen ("Artikel.tex", "w"))
	{
	  /* Fonts definieren */
	  if (fprintf (file, "\\input listmacro\n") < 0)
	    ok = FALSE;

	  if (ok && fprintf (file, "\\headline=\\artheadline\n"
	                     "\\def\\headname{Artikelliste}\n") < 0)
	    ok = FALSE;

	  if (mode == 0)
	    {
	      /* alle Kategorien ausgeben */
	      for (i = 0; ok && i < A_GetCategoryCount (); i++)
		{
		  A_GetCategory (i, commbuff);
		  ok = printArticleCategory (commbuff, mode, file);
		}
	    }
	  else
	    {
	      /* nur aktuelle Kategorien ausgeben */

	      if (ok)
		ok = printArticleCategory (str, mode, file);

	    }
	  if (ok && fprintf (file, "\\bye\n") < 0)
	    ok = FALSE;

	  if (!ok)
	    result = error = ERR_PRINT_SAVE;

	  fclose (file);
	}
      else
	result = error = ERR_PRINT_SAVE;

      if (!result)
	{
	  incon = Open (ConWin, MODE_OLDFILE);
	  if (incon)
	    {

	      DVIprintTags[0].ti_Data = incon;

	      sprintf (commbuff, "%s &%s Artikel.tex", CO_GetTeXName (),
	               CO_GetFormatName ());

	      ret = SystemTagList (commbuff, DVIprintTags);
	      if (ret >= 0 && ret < 20)
		{
		  /*
		  **  DVIprint aufrufen
		  */

		  sprintf (commbuff, "%s HOFFSET=%ldtruemm VOFFSET=%ldtruemm "
			   "FROM 1 TO 1000 PRINTER %s UNI off NOLOG "
			   "Artikel.dvi", CO_GetPrintName (),
			   CO_GetDVIHoffset (), CO_GetDVIVoffset (),
			   CO_GetDVIprinter ());

		  if (!SystemTagList (commbuff, DVIprintTags))
		    {
		      /* alles ok, nichts mehr machen... */
		    }
		  else
		    result = error = ERR_PRINT_PRINTING;

		}
	      else
		result = error = ERR_PRINT_PRINTING;

	      Delay (50);
	      Close (incon);
	    }
	  else
	    {
	      if (incon)
		Close (incon);
	      result = error = ERR_PRINT_CON;
	    }
	}

      CurrentDir (olddir);
      UnLock (newdir);
    }
  else
    result = error = ERR_PRINT_PATH;

  return (result);
}

/*
** Ausgabe einer Artikelkategorie
*/

static BOOL 
printArticleCategory (STRPTR category, ULONG mode, FILE * file)
{
  BOOL ok = TRUE;
  struct Article art;
  int i;
  char buf1[200], buf2[200];
  char buf3[100], buf4[30], buf5[30], buf6[30], buf7[30], buf8[30];

  /* überschrift ausgeben */
  strcpy (buf1, category);
  ParseTeXLine (buf1, 199, FALSE);
  if (ok && fprintf (file, "\\category|%s|%%\n", buf1) < 0)
    ok = FALSE;

  for (i = 0; ok && i < A_GetArticleCount (); i++)
    {
      A_GetItem (i, &art);
      if (!stricmp (category, art.Kategorie))
	{
	  strcpy (buf1, art.Artikelnummer);
	  ParseTeXLine (buf1, 99, FALSE);

	  strcpy (buf2, art.Bezeichnung);
	  ParseTeXLine (buf2, 199, FALSE);

	  DisplayBetragOhneDM (buf3, art.Betrag,
	                       CO_GetMwSt (art.Preistabelle), 1);
	  ParseTeXLine (buf3, 99, FALSE);

	  DisplayBetragOhneDM (buf4, art.EKBetrag, 0.0, 0);
	  ParseTeXLine (buf4, 99, FALSE);

	  DisplayBetragOhneDM (buf5, art.EKVersand, 0.0, 0);
	  ParseTeXLine (buf5, 99, FALSE);

	  DisplayBetragOhneDM (buf6, art.EKBetrag + art.EKVersand,
	                       CO_GetMwSt (art.Preistabelle), 1);
	  ParseTeXLine (buf6, 99, FALSE);

	  /* 3.3.96, ss: Menge = Lagerbestand mit ausgeben */
	  PrintMonetary (buf7, art.Menge);
	  ParseTeXLine (buf7, 99, FALSE);

	  strcpy (buf8, Locale->loc_MonCS);

	  if (ok && fprintf (file,
	                     "\\articleline|%s|%s|%s|%s|%s|%s|%s|%s|%%\n",
			     buf1, buf2, buf3, buf4, buf5, buf6, buf7,
			     buf8) < 0)
	    ok = FALSE;
	}
    }

  return (ok);
}
