ftp.nice.ch/pub/next/database/plz/xplz.3.4.s.tar.gz#/xplz-3.4/cui.c

This is cui.c in view mode; [Download] [Up]

/* $Id$ */

/* 
 * Copyright 1993 Rainer Klute <klute@irb.informatik.uni-dortmund.de>
 *
 * Permission to use, copy, modify, distribute, and sell this software and
 * its documentation for any purpose is hereby granted without fee, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation. The author makes no representations about the suitability
 * of this software for any purpose. It is provided "as is" without express
 * or implied warranty.
 *
 */

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

#include "cui.h"

#include "xplz.h"
#include "batch.h"
#include "convert.h"
#include "patchlevel.h"
#include "message.h"
#include "strada.h"
#include "ui.h"
#include "utils.h"




static void CuiMsgFlush (UiComponents *uc)
{
    fprintf (stderr, "\n");
}

static void CuiMsgWrite (UiComponents *uc, char *msg)
{
    fprintf (stderr, msg);
}

#define CuiNoteWrite CuiMsgWrite

static void CuiNoteClear (UiComponents *uc)
{}

#define CuiNoteFlush CuiMsgFlush




static Boolean RecordRead (char *record)
{
    Note (".");
    return True;
}

static Boolean PofadaRecordRead (char *record)
{
    return RecordRead (record);
}

static Boolean StradaRecordRead (char *record)
{
    return RecordRead (record);
}

static Boolean UmsdaRecordRead (char *record)
{
    return RecordRead (record);
}

static Boolean OrtardaRecordRead (char *record)
{
    return RecordRead (record);
}




static void CuiPostfachliste (PofadaSet *pofadaSet, char *ortsname)
{
    Pofada *l;
    Pofada *newPobox;
    int i, j;
    char msg[300];
    char *isoMsg;
    int entriesLeft = pofadaSet->entries;
    char postanstalt[5];

    newPobox = pofadaSet->list;
    postanstalt[0] = '\0';
    for (l = pofadaSet->list, i = j = 0; i < pofadaSet->entries; i++, l++)
    {
	msg[0] = '\0';
	if (strncmp (l->npanst, postanstalt, sizeof (l->npanst)) != 0)
	{
	    strncpy (postanstalt, l->npanst, sizeof (l->npanst));
	    strncat (msg, l->plz_w_o, sizeof (l->plz_w_o));
	    strncat (msg, l->plzalt, sizeof (l->plzalt));
    	    strcat  (msg, " ");
    	    strncat (msg, ortsname, sizeof (((Umsda *) 0)->ortname_a));
    	    StripBlanks (msg);
    	    strcat  (msg, " ");
    	    strncat (msg, l->npanst, sizeof (l->npanst));
	}
	else
	{
	    entriesLeft--;
	    continue;
	}

#if defined (HANDLE_BROKEN_DATAFILES)
	isoMsg = IbmAndBrokenToIso (msg);
#else
	isoMsg = IbmToIso (msg);
#endif
	Message (isoMsg);
	MessageFlush ();
	free (isoMsg);
    }
}




static void AppendHn (char *s, char *tag, int length)
{
    char *c = tag;

    while (*c == ' ' && c - tag < length)
	c++;
    if (c - tag < length)
    {
	strncat (s, c, length - (c - tag));
	StripBlanks (s);
    }
}




static void CuiStrassenliste (PlzConversion *pc)
{
    Strada *l;
    Strada *newStreet;
    int i, j;
    char msg[300];
    char *isoMsg;
    char ortsteil[sizeof (((Strada *) 0)->ortsteil)];
    char sname[sizeof (((Strada *) 0)->sname)];
    char strlfdnr[sizeof (((Strada *) 0)->strlfdnr)];
    int entriesLeft;

    if (pc->strassen == (StradaSet *) 0)
    {
	if (pc->orte->entries > 0)
	    pc->strassen = Strassenverzeichnis (pc->orte->list[0].alort);
	else if (pc->archivOrte->entries > 0)
	    pc->strassen = Strassenverzeichnis (pc->archivOrte->list[0].alort);
    }

    entriesLeft = pc->strassen->entries;
    newStreet = pc->strassen->list;
    ortsteil[0] = sname[0] = strlfdnr[0] = '\0';
    for (l = pc->strassen->list, i = j = 0; i < pc->strassen->entries; i++, l++)
    {
	/* neue Postleitzahl: */
	msg[0] = '\0';
	strncat (msg, l->plz_z, sizeof (l->plz_z));
	strcat (msg, " ");

	/* Straßenname: */
	strncat (msg, l->sname, sizeof (l->sname));
	StripBlanks (msg);
	isoMsg = IbmToIso (msg);

	/* Hausnummernbereich (falls vorhanden): */
	if (strntoi (l->nplz_z, sizeof (l->nplz_z)) > 1)
	{
	    Message (isoMsg);
	    free (isoMsg);
	    Message (", ");
	    msg[0] = '\0';
	    AppendHn (msg, l->hnr1von, sizeof (l->hnr1von));
	    AppendHn (msg, l->hnr2von, sizeof (l->hnr2von));
	    strcat (msg, "-");
	    AppendHn (msg, l->hnr1bis, sizeof (l->hnr1bis));
	    AppendHn (msg, l->hnr2bis, sizeof (l->hnr2bis));
	    isoMsg = IbmToIso (msg);
	    Message (isoMsg);
	    free (isoMsg);
	}
	else
	{
	    if (strncmp (l->sname, sname, sizeof (l->sname)) != 0
	    || strncmp (l->strlfdnr, strlfdnr, sizeof (l->strlfdnr)) != 0)
	    {
		Message (isoMsg);
	        free (isoMsg);
		strncpy (sname, l->sname, sizeof (l->sname));
		strncpy (strlfdnr, l->strlfdnr, sizeof (l->strlfdnr));
	    }
	    else
	    {
		entriesLeft--;
		continue;
	    }
	}

	/* Orts-String (bei mehreren gleichnamigen Straßen): */
	if (strntoi (l->anzgleist, sizeof (l->anzgleist)) > 1)
	{
	    if (strncmp (l->ortsteil, ortsteil, sizeof (l->ortsteil)) != 0)
	    {
		strncpy (ortsteil, l->ortsteil, sizeof (l->ortsteil));
		strcpy (msg, ", ");
		strncat (msg, l->plz_w_o, sizeof (l->plz_w_o));
	    	StripBlanks (msg);
		strncat (msg, l->plzalt, sizeof (l->plzalt));
	    	strcat  (msg, " ");
	    	strncat (msg, pc->ort, sizeof (((Umsda *) 0)->ortname_a));
	    	StripBlanks (msg);
	    	strcat  (msg, " ");
	    	strncat (msg, l->npanst, sizeof (l->npanst));
	    	StripBlanks (msg);
	    	strcat  (msg, " (");
		strncat (msg, l->ortsteil, sizeof (l->ortsteil));
	    	StripBlanks (msg);
            	strcat  (msg, ")");
	    	StripBlanks (msg);
		isoMsg = IbmToIso (msg);
		Message (isoMsg);
		free (isoMsg);
	    }
	    else
	    {
		entriesLeft--;
		continue;
	    }
	}
    MessageFlush ();
    }
}




static void PlzFound (Batch *batch)
{
    PlzConversion *pc = batch->pc;
    char *help1, *help2;
    char ortString[300];

    help1 = ColumnReplace (batch->inputRecord, batch->columnStreet,
			   batch->separator,
			   StrasseString (pc->strasse, pc->hausnummer,
					  pc->postfach));
    if (batch->columnPlz > 0 && batch->columnPlz != batch->columnPlace)
    {
	help2 = ColumnReplace (help1, batch->columnPlz, batch->separator,
			       pc->plz_neu);
	free (help1);
	help1 = help2;
	help2 = ColumnReplace (help1, batch->columnPlace, batch->separator,
			       pc->ort);
    }
    else
    {
	sprintf (ortString, "%s %s", pc->plz_neu, pc->ort);
	help2 = ColumnReplace (help1, batch->columnPlace, batch->separator,
			       ortString);
    }
    FputsCharSet (help2, batch->ofl, batch->outputFormat);
    free (help1);
    free (help2);
}




static void PlzNotFound (Batch *batch)
{
    FputsCharSet (batch->inputRecord, batch->efl, batch->outputFormat);
}




static void CuiOrtsliste (UmsdaSet *orte, OrtardaSet *archivOrte)
{
    Umsda *lu;
    Ortarda *lo;
    int i;
    char msg[300];
    char *isoMsg;
    char *c;

    for (lu = orte->list, i = 0; i < orte->entries; i++)
    {
	/* PLZ alt, Ortsname, Postanstalt: */
	msg[0] = '\0';
	strncat (msg, lu->plz_w_o, sizeof (lu->plz_w_o));
	strncat (msg, lu->plzalt, sizeof (lu->plzalt));
        strcat  (msg, " ");
        strncat (msg, lu->ortname_a, sizeof (lu->ortname_a));
	StripBlanks (msg);
        strcat  (msg, " ");
        strncat (msg, lu->npanst_a, sizeof (lu->npanst_a));
	StripBlanks (msg);
	isoMsg = IbmToIso (msg);
	Message (isoMsg);
	free (isoMsg);

	/* Ortszusatz: */
	*msg = '\0';
	c = lu->ortzusa;
	if (*c != ',' && *c != '-')
	    strcat (msg, " ");
	while (*c == ' ' && c - lu->ortzusa < sizeof (lu->ortzusa))
	    c++;
	if (c - lu->ortzusa < sizeof (lu->ortzusa))
	    strncat (msg, c, sizeof (lu->ortzusa) - (c - lu->ortzusa));
	StripBlanks (msg);

	isoMsg = IbmToIso (msg);
	Message (isoMsg);
	MessageFlush ();
	free (isoMsg);
	lu++;
    }

    for (lo = archivOrte->list; i < orte->entries + archivOrte->entries; i++)
    {
	/* PLZ alt, Ortsname, Postanstalt: */
	msg[0] = '\0';
	strncat (msg, lo->plz_w_o, sizeof (lo->plz_w_o));
	strncat (msg, lo->plzalt, sizeof (lo->plzalt));
        strcat  (msg, " ");
        strncat (msg, lo->ortname_a, sizeof (lo->ortname_a));
	StripBlanks (msg);
        strcat  (msg, " ");
        strncat (msg, lo->npanst_a, sizeof (lo->npanst_a));
	StripBlanks (msg);
	isoMsg = IbmToIso (msg);
	Message (isoMsg);
	free (isoMsg);

	/* aktueller Ortsname: */
	strcpy (msg, " -> ");
	strncat (msg, lo->ortname_n, sizeof (lo->ortname_n));
	StripBlanks (msg);

	isoMsg = IbmToIso (msg);
	Message (isoMsg);
	MessageFlush ();
	free (isoMsg);
	lo++;
    }
    MessageFlush ();
}




struct Optionen
{
    char *string;
    enum {OptionDisplay, OptionOrt, OptionStrasse, OptionVerzeichnis,
          OptionStapelbetrieb, OptionEingabedatei, OptionAusgabedatei,
          OptionFehlerdatei, OptionTrennzeichen, OptionPostleitzahl,
          OptionZeichensatz, OptionVerkehrsgebiet} option;
};




int Option (struct Optionen optionen[], int numOptionen, char *s)
{
    int i;
    int bestMatchValue = 0;
    int bestMatchOption = -1;
    int cmp;
    char *h;
    char *s1;
    char *o1;
    int len;

    h = IbmToIso (s);
    s1 = IsoToCapitals (h);
    free (h);
    for (i = 0; i < numOptionen; i++)
    {
	h = IbmToIso (optionen[i].string);
	o1 = IsoToCapitals (h);
	free (h);
	len = strlen (s1);
	cmp = strncmp (s1, o1, len);
	free (o1);
	if (cmp == 0)
	{
	    if (len == strlen (o1))
	    {
		bestMatchOption = optionen[i].option;
		break;
	    }
	    else if (len != bestMatchValue)
	    {
		bestMatchValue = len;
		bestMatchOption = optionen[i].option;
	    }
	    else
	    {
		bestMatchOption = -1;
	        break;
	    }
	}
    }
    free (s1);
    return bestMatchOption;
}




void CuiInterface (int argc, char *argv[])
{
    static ConversionData cd;
    static PlzConversion pcs;
    PlzConversion *pc = &pcs;
    Boolean verzeichnis = False;
    Boolean stapelbetrieb = False;
    Boolean fehler = False;
    char c;
    char string[300];
    char *strasse, *hausnummer, *postfach, *plz_alt, *ort, *postanstalt,
	 *ortsteil;
    char *plz_neu;
    char **p;

    static struct Optionen optionen[] =
    {{"Display",        OptionDisplay},
     {"Ort",            OptionOrt},
     {"Strasse",        OptionStrasse},
     {"Verzeichnis",    OptionVerzeichnis},
     {"Stapelbetrieb",  OptionStapelbetrieb},
     {"Eingabedatei",   OptionEingabedatei},
     {"Ausgabedatei",   OptionAusgabedatei},
     {"Fehlerdatei",    OptionFehlerdatei},
     {"Trennzeichen",   OptionTrennzeichen},
     {"Postleitzahl",   OptionPostleitzahl},
     {"PLZ",            OptionPostleitzahl},
     {"Zeichensatz",    OptionZeichensatz},
     {"Verkehrsgebiet", OptionVerkehrsgebiet}
    };

    ort = strasse = plz_neu = strdup ("");

    cd.pc = &pcs;
    cd.pc->plz_alt = (char *) 0;
    cd.pc->ort = (char *) 0;
    cd.pc->postanstalt = (char *) 0;
    cd.pc->ortsteil = (char *) 0;
    cd.pc->strasse = (char *) 0;
    cd.pc->hausnummer = (char *) 0;
    cd.pc->postfach = (char *) 0;
    cd.pc->plz_neu = (char *) 0;
    cd.pc->verkehrsgebiet = 'W';
    cd.pc->orte = (UmsdaSet *) 0;
    cd.pc->strassen = (StradaSet *) 0;
    cd.pc->postfaecher = (PofadaSet *) 0;

    cd.batch = (Batch *) calloc (1, sizeof (Batch));
    UpdateString (&(cd.batch->inputFile), "");
    UpdateString (&(cd.batch->outputFile), "");
    UpdateString (&(cd.batch->errorFile), "");
    cd.batch->separator = ',';
    cd.batch->columnStreet = -1;
    cd.batch->columnPlz = -1;
    cd.batch->columnPlace = -1;
    cd.batch->outputFormat = OutputISO;
    cd.batch->ifl = (FILE *) 0;
    cd.batch->ofl = (FILE *) 0;
    cd.batch->efl = (FILE *) 0;
    cd.batch->pc = cd.pc;
    cd.batch->fehlerAnhalten = False;
    cd.batch->userData = &cd;
    cd.batch->status = BatchInit;
    cd.batch->inputRecord = (char *) 0;
    cd.batch->successCallback = PlzFound;
    cd.batch->failureCallback = PlzNotFound;
    cd.batch->beforeConvertCallback = (void (*)()) 0;
    cd.batch->afterConvertCallback = (void (*)()) 0;
    cd.batch->finishedCallback = (void (*)()) 0;

    userInterfaceMethods.NoteClear = CuiNoteClear;
    userInterfaceMethods.NoteWrite = CuiNoteWrite;
    userInterfaceMethods.MsgWrite = CuiMsgWrite;
    userInterfaceMethods.MsgFlush = CuiMsgFlush;

    userInterfaceMethods.PofadaRecordRead = PofadaRecordRead;
    userInterfaceMethods.StradaRecordRead = StradaRecordRead;
    userInterfaceMethods.UmsdaRecordRead = UmsdaRecordRead;
    userInterfaceMethods.OrtardaRecordRead = OrtardaRecordRead;

    Message ("\nxplz ");
    Message (RELEASE);
    Message (" - Das Postleitzahlenbuch\n");
    Message ("© 1993 Rainer Klute, Universität Dortmund, IRB\n");
    MessageFlush ();

    for (p = argv + 1; *p != (char *) 0; p++)
    {
	switch (Option (optionen, sizeof (optionen) / sizeof (optionen[0]), *p))
	{
	    case OptionDisplay:
	    {
		p++;
		break;
	    }
	    case OptionOrt:
	    {
		ort = strdup (*(++p));
		break;
	    }
	    case OptionStrasse:
	    {
		strasse = strdup (*(++p));
		break;
	    }
	    case OptionVerzeichnis:
	    {
		verzeichnis = True;
		break;
	    }
	    case OptionStapelbetrieb:
	    {
		stapelbetrieb = True;
		break;
	    }
	    case OptionEingabedatei:
	    {
		cd.batch->inputFile = *(++p);
		break;
	    }
	    case OptionAusgabedatei:
	    {
		cd.batch->outputFile = *(++p);
		break;
	    }
	    case OptionFehlerdatei:
	    {
		cd.batch->errorFile = *(++p);
		break;
	    }
	    case OptionTrennzeichen:
	    {
		cd.batch->separator = **(++p);
		break;
	    }
	    case OptionPostleitzahl:
	    {
		cd.batch->columnPlz = atoi (*(++p));
		break;
	    }
	    case OptionZeichensatz:
	    {
		p++;
		if (strcmp (*p, "IBM") == 0 || strcmp (*p, "ibm") == 0)
		    cd.batch->outputFormat = OutputIBM;
		else if (strcmp (*p, "ISO") == 0
		|| strcmp (*p, "iso") == 0
	        || strcmp (*p, "ISO8859-1") == 0
	        || strcmp (*p, "iso8859-1") == 0
	        || strcmp (*p, "ISO-8859-1") == 0
	        || strcmp (*p, "iso-8859-1") == 0)
		    cd.batch->outputFormat = OutputISO;
		else if (strcmp (*p, "ATARI") == 0
		|| strcmp (*p, "atari") == 0)
		    cd.batch->outputFormat = OutputAtari;
		else
		{
		    fprintf (stderr,
		        "Unbekannter Ausgabezeichensatz: -z %s\n\n", *p);
		    fehler = True;
	        }
		break;
	    }
	    case OptionVerkehrsgebiet:
	    {
	    	if (**p == 'O' || **p == 'o' || **p == 'W' || **p == 'w')
		    cd.pc->verkehrsgebiet = toupper (**p);
		break;
	    }
	    default:
		fehler = True;
	}
    }
    if (cd.batch->columnPlz == -1)
	cd.batch->columnPlz = cd.batch->columnPlace;

    if (fehler || !*ort)
    {
	fputs ("Aufruf: ", stderr);
	fputs (argv[0], stderr);
	fputs ("\n", stderr);
	fputs ("         -ort [PLZ-alt] Ort [Postanstalt] [(Ortsteil)]\n", stderr);
	fputs ("         [-strasse {Strasse [Hausnr.]|\"Postfach\" Nr.}]\n", stderr);
	fputs ("         [-verzeichnis]\n", stderr);
	fputs ("         [-verkehrsgebiet {W | O}]\n", stderr);
	fputs ("\n", stderr);
	fputs ("oder:\n", stderr);
	fputs ("\n", stderr);
	fputs ("        ", stderr);
	fputs (argv[0], stderr);
	fputs ("\n", stderr);
	fputs ("         -stapelbetrieb\n", stderr);
	fputs ("         -eingabedatei name\n", stderr);
	fputs ("         -ausgabedatei name\n", stderr);
	fputs ("         -fehlerdatei name\n", stderr);
	fputs ("         -trennzeichen t\n", stderr);
	fputs ("         -ort spalte\n", stderr);
	fputs ("         -strasse spalte\n", stderr);
	fputs ("         [{-postleitzahl | -plz} spalte]\n", stderr);
	fputs ("         [-verkehrsgebiet {W | O}]\n", stderr);
	fputs ("         [-zeichensatz {ISO-8859-1 | IBM | ATARI}]\n", stderr);
	fputs ("\n", stderr);
	fputs ("Alle Optionen können bis auf Eindeutigkeit abgekürzt werden.\n", stderr);
	fputs ("\n", stderr);
	return;
    }

    if (stapelbetrieb)
    {
	if (atoi (strasse))
	    cd.batch->columnStreet = atoi (strasse);
	if (atoi (ort))
	    cd.batch->columnPlace = atoi (ort);
	while (!BatchConvert (cd.batch))
	    ;
    }
    else
    {
	strcpy (string, strasse);
	ParseStrasse (string, &strasse, &hausnummer, &postfach);
	strcpy (string, ort);
	ParseOrt (string, &plz_alt, &ort, &postanstalt, &ortsteil);
	ConvertPlz (pc, strasse, hausnummer, postfach, plz_alt, ort,
		    postanstalt, ortsteil);
	free (strasse);
	free (hausnummer);
	free (postfach);
	free (plz_alt);
	free (ort);
	free (postanstalt);
	free (ortsteil);
        MessageFlush();

        if (IsOrtGefunden (pc))
        {
	    if (!IsOrtEindeutig (pc))
	    {
	        /* Mehrere PLZ, möglicherweise auch mehrere Orte */
	        if (verzeichnis)
		    CuiOrtsliste (pc->orte, pc->archivOrte);
	    }

	    if (pc->status == PlzPlzNeuGefunden)
	        plz_neu = strdup (pc->plz_neu);

	    strcpy (string, OrtString (pc->plz_alt, pc->ort, pc->postanstalt,
		    pc->ortsteil));
	    ort = strdup (string);
        }

        if (IsStrasseGefunden (pc))
        {
	    strcpy (string, StrasseString (pc->strasse, pc->hausnummer,
		    pc->postfach));
	    strasse = strdup (string);
	    if (!IsStrasseEindeutig (pc) && verzeichnis)
	        CuiStrassenliste (pc);
        }

        if (IsPostfachGefunden (pc))
        {
	    strcpy (string, "Postfach ");
	    strcat (string, pc->postfach);
	    strasse = strdup (string);
	    if (!IsPostfachEindeutig (pc) && verzeichnis)
	        CuiPostfachliste (pc->postfaecher, pc->orte->list->ortname_a);
        }

        if (IsOrtGefunden (pc) && verzeichnis)
        {
	    if (*(pc->strasse) && (!IsStrasseGefunden (pc)
	    || !IsStrasseEindeutig (pc)))
	        CuiStrassenliste (pc);	
        }

        if (IsStrasseGefunden (pc) || IsPostfachGefunden (pc))
        {
	    Message (strasse);
            Message (", ");
        }
        if (IsOrtGefunden (pc))
	    Message (ort);
        if (pc->status == PlzPlzNeuGefunden)
        {
	    Message (" --> ");
	    Message (plz_neu);
	    Message (" ");
	    Message (pc->ort);
	    MessageFlush ();
        }
        else
        {
	    Message ("\n");
	    Message (ConversionStatusString (pc->status));
	    MessageFlush ();
        }
    }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.