
/****************************************************************************
** Leistungsorientierte Krankenanstaltenfinanzierung (LKF)                 **
** Scoring-C-Sourcen V2026.1                                               **
** (C) 2026 BMASGPK                                                        **
*****************************************************************************
** satzchk5.c - Routinen zur Überprüfung des Dateninputs                   **
**                                                                         **
**		 Alex.Holzer@chello.at                                             **
**       Bernhard.Pesec@dothealth.at                                       **
***************************************************************************/

#include "lkfint5.h"
#include "lkfstru5.h"

#define CHECK_SATZARTEN_COUNT		7
static const char *check_satzarten[CHECK_SATZARTEN_COUNT] = 
	{"L01", "L02", "L03", "L04", "R01", "R02", "S01"};

static int lkf_satzart_check_gen (LKF_CONTEXT *pContext, const char **ppSatzartString, unsigned int satzart_count)
{
	unsigned int i, j;
	const char ***pppSatzartRecords;
	const SATZART_INFO **ppSatzart;
	const LKF_SATZART_DEFS *pDefs;
	unsigned int *pSatzartCount;
	
	pDefs = SatzartDef_Init (pContext->modelljahr);

	if (pDefs) {

		pppSatzartRecords = (const char ***) LKF_CALLOC (pContext, "lkf_satzart_check_gen.rec", satzart_count, sizeof(const char **));
        if (!pppSatzartRecords) return LKF_OUTOFMEMORY_ERROR;
		ppSatzart = (const SATZART_INFO **) LKF_CALLOC (pContext, "lkf_satzart_check_gen.satz", satzart_count, sizeof (const SATZART_INFO *));
        if (!ppSatzart) {
            LKF_FREE(pContext, "lkf_satzart_check_gen.rec", pppSatzartRecords);
            return LKF_OUTOFMEMORY_ERROR;
        }
		pSatzartCount = (unsigned int *) LKF_CALLOC (pContext, "lkf_satzart_check_gen.count", satzart_count, sizeof (unsigned int));
        if (!pSatzartCount) {
            LKF_FREE(pContext, "lkf_satzart_check_gen.rec", pppSatzartRecords);
            LKF_FREE(pContext, "lkf_satzart_check_gen.satz", ppSatzart);
            return LKF_OUTOFMEMORY_ERROR;
        }
        
		for (i = 0; i < satzart_count; i++) {
			ppSatzart[i] = Satzart_GetSatzart (pDefs, ppSatzartString[i]);
			
			if (ppSatzart[i])
				pSatzartCount[i] = Satzart_GetLinesAlloc (pContext->pLineBuffer, ppSatzart[i]->pSatzart, &pppSatzartRecords[i]);
			else
				pSatzartCount[i] = 0;
		}

		for (i = 0; i < satzart_count; i++) {

			if (!ppSatzart[i])
				continue;

			for (j = 0; j < pSatzartCount[i]; j++) {
				Satzart_Check (pContext, pppSatzartRecords[i][j], ppSatzart[i], pContext->pCheckContext);
			}
		}

		for (i = 0; i < satzart_count; i++) {
			if (ppSatzart[i])
				Satzart_GetLinesFree (pContext, pppSatzartRecords[i]);
		}

		LKF_FREE (pContext, "lkf_satzart_check_gen", pSatzartCount);
		LKF_FREE (pContext, "lkf_satzart_check_gen", (void *) ppSatzart);
		LKF_FREE (pContext, "lkf_satzart_check_gen", (void *) pppSatzartRecords);

	}
    return 0;
}

static int fill_context_abteilungen (LKF_CONTEXT *pContext, LKF_CHECK_CONTEXT *pCheckContext, LKF_KK_CONTEXT *pKKContext)
{
    char sKst[10];
    char sAbtFC[10];
    char sKANR6[8];
	const SATZART_INFO *pK01;
	unsigned int i;
	if (!pContext || !pCheckContext || !pKKContext)
		return 0;
	pK01 = pKKContext->ppKKSatzarten[0];

    if (pContext->modelljahr >= 2017) {
        
        const LKF_EXPANDED_LINE **k01Lines = pKKContext->pppExpandedLines[0];
        
        for (i = 0; i < pKKContext->pSatzartCount[0]; i++)
        {
            Satzart_GetValueStringExp (k01Lines[i], pK01->ppRef[GEN_ABTFC], sAbtFC, 10);
            Satzart_GetValueStringExp (k01Lines[i], pK01->ppRef[K01_INT_KOSTNR], sKst, 10);
            Satzart_GetValueStringExp (k01Lines[i], pK01->ppRef[GEN_KANR], sKANR6, 8);
            if (!lkf_context_add_abteilung (pContext, sAbtFC, sKst, sKANR6)) {
                return LKF_OUTOFMEMORY_ERROR;
            }
        }
    } else {
        unsigned int len;
        const char *ds;
        for (i = 0; i < pKKContext->pSatzartCount[0]; i++)
        {
            ds = pKKContext->pppSatzartRecords[0][i];
            len = pKKContext->ppSatzartRecordLen[0][i];
            
            Satzart_GetValueString (ds, len, pK01->ppRef[GEN_ABTFC], sAbtFC, 10);
            Satzart_GetValueString (ds, len, pK01->ppRef[K01_INT_KOSTNR], sKst, 10);
            Satzart_GetValueString (ds, len, pK01->ppRef[GEN_KANR], sKANR6, 8);
            lkf_context_add_abteilung (pContext, sAbtFC, sKst, sKANR6);
        }
    }
    
	lkf_context_sort_abteilungen (pContext);
    return 0;
}

_SCORING_EXPORT unsigned int lkf_check_nombds (LKF_CONTEXT *pContext, unsigned int modus)
{ /* V21.0 */
    unsigned int i;
    if (pContext->pSatzartErrors) {
        LKF_AUFENTHALT **ppAufenthalt;
        Satzart_FreeErrorStructure (pContext, pContext->pSatzartErrors);
        pContext->pSatzartErrors = 0;
        ppAufenthalt = pContext->ppAufenthalt;
        for (i = 0; i < pContext->patient_anz; i++, ++ppAufenthalt) {
            (*ppAufenthalt)->nSatzartFirstError = -1;
            (*ppAufenthalt)->nSatzartNextError = -1;
        }
    }
    
    /* Import-Errors übertragen */
    if (!(pContext->flags & LKFCONTEXT_NUR_MBDS) && pContext->nImportErrorCount)
    {
        for (i = 0; i < pContext->nImportErrorCount; i++)
        {
            LKF_IMPORTERROR_STRUC *pImportError = pContext->pImportError + i;
            Satzart_ReportError (pContext, 0, lkf_get_line (pContext->pErrorLineBuffer, pImportError->nLine), 0, pImportError->pSatzartInfo, pImportError->pFeld, pImportError->pErrorDef, pImportError->text);
        }
    }
    
    pContext->pCheckContext = lkf_get_contextcheckcontext (pContext);
    if (!pContext->pCheckContext->pKKContext) {
        pContext->pCheckContext->pKKContext = lkf_alloc_kk_context (pContext);
        if (!pContext->pCheckContext->pKKContext) return LKF_OUTOFMEMORY_UINTERROR;
    }
    /* Ueberpruefung der KK-Satzarten */
    pContext->pCheckContext->pAufenthalt = 0;
    pContext->pCheckContext->nTraceFacility = LKF_FAC_KAS_KORE;
    pContext->pCheckContext->pCurrentCheck = 0;
        
    lkf_check_kk (pContext, pContext->pCheckContext->pKKContext);
    lkf_satzart_check_gen (pContext, check_satzarten, CHECK_SATZARTEN_COUNT);
    
    lkf_free_kk_context (pContext->pCheckContext->pKKContext);
    pContext->pCheckContext->pKKContext = 0;
    lkf_trace_finished (pContext);
    return 0;
}

_SCORING_EXPORT unsigned int lkf_check (LKF_CONTEXT *pContext, unsigned int modus)
{
    unsigned int i;

    int ret = 0;
	if (pContext->pSatzartErrors) {
        LKF_AUFENTHALT *pAufenthalt;
		Satzart_FreeErrorStructure (pContext, pContext->pSatzartErrors);
		pContext->pSatzartErrors = 0;
        for (i = 0; i < pContext->patient_anz; i++) {
            pAufenthalt = pContext->ppAufenthalt[i];
            pAufenthalt->nSatzartFirstError = -1;
            pAufenthalt->nSatzartNextError = -1;
        }
	}
    if (pContext->ppFilteredErrors) {
        LKF_FREE (pContext, "lkf_check", (void *)pContext->ppFilteredErrors);
        pContext->ppFilteredErrors = 0;
        pContext->nFilteredErrors = 0;
    }

    pContext->executionCalled |= 1;
	ret = lkf_stamm_check_consistency (pContext);
    if (ret == LKF_OUTOFMEMORY_ERROR) return LKF_OUTOFMEMORY_UINTERROR;
	if (ret < 0) return (unsigned int) (10000 - ret);

	/* Import-Errors übertragen */
	if (!(pContext->flags & LKFCONTEXT_NUR_MBDS) && pContext->nImportErrorCount)
	{
		for (i = 0; i < pContext->nImportErrorCount; i++)
		{
            LKF_IMPORTERROR_STRUC *pImportError = pContext->pImportError + i;
			Satzart_ReportError (pContext, 0, lkf_get_line (pContext->pErrorLineBuffer, pImportError->nLine), 0, pImportError->pSatzartInfo, pImportError->pFeld, pImportError->pErrorDef, pImportError->text);
		}
	}
    
    if (pContext->pIntScoring) lkf_int_free_structure (pContext);
    
    for (i = 0; i < pContext->patient_anz; i++) {
        lkf_sort_auf_abt (pContext->ppAufenthalt[i]);
    }
        
#ifdef SUPPORT_PRE2017
    if (pContext->modelljahr >= 2017)
        lkf_int_alloc_structure_2017 (pContext);
    else
        lkf_int_alloc_structure (pContext);
#else
    ret = lkf_int_alloc_structure_2017 (pContext);
    if (ret == LKF_OUTOFMEMORY_ERROR) return LKF_OUTOFMEMORY_UINTERROR;
#endif
    pContext->pCheckContext = lkf_get_contextcheckcontext (pContext);
	if (!pContext->pCheckContext) return LKF_OUTOFMEMORY_UINTERROR;

    if (!pContext->pCheckContext->pKKContext) {
        pContext->pCheckContext->pKKContext = lkf_alloc_kk_context (pContext);
        if (!pContext->pCheckContext->pKKContext) return LKF_OUTOFMEMORY_UINTERROR;
    }
    
    if (pContext->modelljahr >= 2024) {
        lkf_SpezListCheck (pContext);
    }
    
    ret = lkf_context_plaus (pContext, 0);
    if (ret == LKF_OUTOFMEMORY_ERROR) return LKF_OUTOFMEMORY_UINTERROR;

    pContext->executionCalled |= 2;
    if (!(pContext->flags & LKFCONTEXT_NUR_MBDS))
    {
        lkf_int_analyse (pContext);
        
        
        /* Ueberpruefung der KK-Satzarten */
        pContext->pCheckContext->pAufenthalt = 0;
        pContext->pCheckContext->nTraceFacility = LKF_FAC_KAS_KORE;
        pContext->pCheckContext->pCurrentCheck = 0;
        
        ret = lkf_check_kk (pContext, pContext->pCheckContext->pKKContext);
        if (ret == LKF_OUTOFMEMORY_ERROR) return LKF_OUTOFMEMORY_UINTERROR;
        if (!ret) {
            ret = lkf_satzart_check_gen (pContext, check_satzarten, CHECK_SATZARTEN_COUNT);
        }
    }
    else if (pContext->flags & LKFCONTEXT_INTENSIV)
        lkf_int_analyse (pContext);
    
    
    lkf_free_kk_context (pContext->pCheckContext->pKKContext);
    pContext->pCheckContext->pKKContext = 0;
    lkf_trace_finished (pContext);
    pContext->executionCalled |= 4;
    if (ret == LKF_OUTOFMEMORY_ERROR) return LKF_OUTOFMEMORY_UINTERROR;
    if (ret < 0) return (unsigned int) (10000 - ret);
    return (unsigned int) ret;
}

_SCORING_EXPORT unsigned int lkf_check_abortable (LKF_CONTEXT *pContext, unsigned int modus, LKFEXECUTION_DELEGATE cb, unsigned int stepSize)
{
    unsigned int i;
    unsigned int count;
    int ret;
    
    if (pContext->pSatzartErrors) {
        LKF_AUFENTHALT **ppAufenthalt;
        Satzart_FreeErrorStructure (pContext, pContext->pSatzartErrors);
        pContext->pSatzartErrors = 0;
        ppAufenthalt = pContext->ppAufenthalt;
        for (i = 0; i < pContext->patient_anz; i++, ++ppAufenthalt) {
            (*ppAufenthalt)->nSatzartFirstError = -1;
            (*ppAufenthalt)->nSatzartNextError = -1;
        }
    }
    if (pContext->ppFilteredErrors) {
        LKF_FREE (pContext, "lkf_check_abortable", (void *)pContext->ppFilteredErrors);
        pContext->ppFilteredErrors = 0;
        pContext->nFilteredErrors = 0;
    }

    ret = lkf_stamm_check_consistency (pContext);
    if (ret < 0) return (unsigned int) (10000 - ret);

    /* Import-Errors übertragen */
    if (!(pContext->flags & LKFCONTEXT_NUR_MBDS) && pContext->nImportErrorCount)
    {
        for (i = 0; i < pContext->nImportErrorCount; i++)
        {
            LKF_IMPORTERROR_STRUC *pImportError = pContext->pImportError + i;
            Satzart_ReportError (pContext, 0, lkf_get_line (pContext->pErrorLineBuffer, pImportError->nLine), 0, pImportError->pSatzartInfo, pImportError->pFeld, pImportError->pErrorDef, pImportError->text);
        }
    }
    
    if (pContext->pIntScoring) lkf_int_free_structure (pContext);
    
    for (i = 0; i < pContext->patient_anz; i++)
        lkf_sort_auf_abt (pContext->ppAufenthalt[i]);
    
#ifdef SUPPORT_PRE2017
    if (pContext->modelljahr >= 2017)
        lkf_int_alloc_structure_2017 (pContext);
    else
        lkf_int_alloc_structure (pContext);
#else
    lkf_int_alloc_structure_2017 (pContext);
#endif
    pContext->pCheckContext = lkf_get_contextcheckcontext (pContext);
    if (!pContext->pCheckContext->pKKContext) {
        pContext->pCheckContext->pKKContext = lkf_alloc_kk_context (pContext);
        if (!pContext->pCheckContext->pKKContext) return LKF_OUTOFMEMORY_ERROR;
    }
    if (cb(pContext, "initialized", 0)) {
        return -99;
    }
    
    count = lkf_get_aufenthalt_anz(pContext);
    
    pContext->plaus_work_count = 0;
    
    for (i = 0; i < count;) {
        i += lkf_context_plaus(pContext, stepSize);
        if (cb(pContext, "plaus", i)) {
            return -99;
        }
    }
    
    if (!(pContext->flags & LKFCONTEXT_NUR_MBDS))
    {
        lkf_int_analyse (pContext);
        
        /* Ueberpruefung der KK-Satzarten */
        pContext->pCheckContext->pAufenthalt = 0;
        pContext->pCheckContext->nTraceFacility = LKF_FAC_KAS_KORE;
        pContext->pCheckContext->pCurrentCheck = 0;
        
        lkf_check_kk (pContext, pContext->pCheckContext->pKKContext);
        lkf_satzart_check_gen (pContext, check_satzarten, CHECK_SATZARTEN_COUNT);
    }
    else if (pContext->flags & LKFCONTEXT_INTENSIV)
        lkf_int_analyse (pContext);
    
    
    lkf_free_kk_context (pContext->pCheckContext->pKKContext);
    pContext->pCheckContext->pKKContext = 0;
    lkf_trace_finished (pContext);
    return 0;
}



LKF_KK_CONTEXT *lkf_alloc_kk_context (LKF_CONTEXT *pContext)
{
	unsigned int i, j, count;
	char sSatzartText[4];
	const LKF_SATZART_DEFS *pDefs;
	LKF_KK_CONTEXT *pKKContext;

	pDefs = SatzartDef_Init (pContext->modelljahr);

	if (pDefs)
	{
		pKKContext = (LKF_KK_CONTEXT *) LKF_CALLOC (pContext, "lkf_alloc_kk_context", 1, sizeof (LKF_KK_CONTEXT));
		if (!pKKContext) return 0;
        pKKContext->pContext = pContext;

		for (i = 0; i < MAX_K_SATZART_NUM; i++) 
		{
			sprintf (sSatzartText, "K%02d", i+1);
			pKKContext->ppKKSatzarten[i] = Satzart_GetSatzart (pDefs, sSatzartText);
            pKKContext->ppSatzartRecordLen[i] = 0;
            if (pContext->modelljahr >= 2017)
            {
                count = Satzart_GetLinesAllocExp (pContext->pExpLineBuffer, pKKContext->ppKKSatzarten[i]->pSatzart, &pKKContext->pppExpandedLines[i]);
                if (count == LKF_OUTOFMEMORY_UINTERROR) {
                    lkf_free_kk_context(pKKContext);
                    return 0;
                }
			}
            else {
                count = Satzart_GetLinesAlloc (pContext->pLineBuffer, pKKContext->ppKKSatzarten[i]->pSatzart, &pKKContext->pppSatzartRecords[i]);
				if (count == LKF_OUTOFMEMORY_UINTERROR) return 0;

				if (count)
                {
                    pKKContext->ppSatzartRecordLen[i] = (unsigned int *) LKF_CALLOC (pContext, "lkf_alloc_kk_context.rl", count, sizeof (unsigned int));
                    if (!pKKContext->ppSatzartRecordLen[i]) return 0;
                    
                    for	(j = 0; j < count; j++)
                    {
                        pKKContext->ppSatzartRecordLen[i][j] = (unsigned int) strlen (pKKContext->pppSatzartRecords[i][j]);
                    }
                }
            }
            pKKContext->pSatzartCount[i] = count;
		}

		for (i = 0; i < MAX_G_SATZART_NUM; i++) 
		{
			sprintf (sSatzartText, "G%02d", i+1);
			pKKContext->ppGGSatzarten[i] = Satzart_GetSatzart (pDefs, sSatzartText);
            pKKContext->ppGGSatzartRecordLen[i] = 0;
            if (pContext->modelljahr >= 2017) {
                count = Satzart_GetLinesAllocExp(pContext->pExpLineBuffer, pKKContext->ppGGSatzarten[i]->pSatzart, &pKKContext->pppGGExpandedLines[i]);
                if (count == LKF_OUTOFMEMORY_UINTERROR) {
                    lkf_free_kk_context(pKKContext);
                    return 0;
                }
			}
            else {
                count = Satzart_GetLinesAlloc (pContext->pLineBuffer, pKKContext->ppGGSatzarten[i]->pSatzart, &pKKContext->pppGGSatzartRecords[i]);
                if (count)
                {
                    pKKContext->ppGGSatzartRecordLen[i] = (unsigned int *) LKF_CALLOC (pContext, "lkf_alloc_kk_context.gg", count, sizeof (unsigned int));
                    if (!pKKContext->ppGGSatzartRecordLen[i]) return 0;
                    
                    for	(j = 0; j < count; j++)
                    {
                        pKKContext->ppGGSatzartRecordLen[i][j] = (unsigned int) strlen (pKKContext->pppGGSatzartRecords[i][j]);
                    }
                }
            }
            pKKContext->pGGSatzartCount[i] = count;
		}

		for (i = 0; i < MAX_B_SATZART_NUM; i++)
		{
			sprintf (sSatzartText, "B%02d", i+1);
			pKKContext->ppBSatzarten[i] = Satzart_GetSatzart (pDefs, sSatzartText);
			pKKContext->ppBSatzartRecordLen[i] = 0;
			if (pKKContext->ppBSatzarten[i])
			{
                if (pContext->modelljahr >= 2017) {
                    count = Satzart_GetLinesAllocExp(pContext->pExpLineBuffer, pKKContext->ppBSatzarten[i]->pSatzart, &pKKContext->pppBBExpandedLines[i]);
                    if (count == LKF_OUTOFMEMORY_UINTERROR) {
                        lkf_free_kk_context(pKKContext);
                        return 0;
                    }
                }
                else {
                    count = Satzart_GetLinesAlloc (pContext->pLineBuffer, pKKContext->ppBSatzarten[i]->pSatzart, &pKKContext->pppBSatzartRecords[i]);
                
                    if (count)
                    {
                        pKKContext->ppBSatzartRecordLen[i] = (unsigned int *) LKF_CALLOC (pContext, "lkf_alloc_kk_context.b", count, sizeof (unsigned int));
                        if (!pKKContext->ppBSatzartRecordLen[i]) {
                            lkf_free_kk_context(pKKContext);
                            return 0;
                        }
                        for	(j = 0; j < count; j++)
                        {
                            pKKContext->ppBSatzartRecordLen[i][j] = (unsigned int) strlen (pKKContext->pppBSatzartRecords[i][j]);
                        }
                    }
                }
                pKKContext->pBSatzartCount[i] = count;
            } else {
                pKKContext->pBSatzartCount[i] = 0;
            }
        }
        
        if (pContext->modelljahr >= SATZART_A_MODEL) {
            for (i = 0; i < MAX_A_SATZART_NUM; i++)
            {
                sprintf (sSatzartText, "A%02d", i+1);
                pKKContext->ppASatzarten[i] = Satzart_GetSatzart (pDefs, sSatzartText);
                pKKContext->ppASatzartRecordLen[i] = 0;
                if (pKKContext->ppASatzarten[i])
                {
                    count = Satzart_GetLinesAllocExp(pContext->pExpLineBuffer, pKKContext->ppASatzarten[i]->pSatzart, &pKKContext->pppAExpandedLines[i]);
                    if (count == LKF_OUTOFMEMORY_UINTERROR) {
                        lkf_free_kk_context(pKKContext);
                        return 0;
                    }
                    pKKContext->pASatzartCount[i] = count;
                } else {
                    pKKContext->pASatzartCount[i] = 0;
                }
            }
        }
        else {
            for (i = 0; i < MAX_A_SATZART_NUM; i++)
            {
                pKKContext->pASatzartCount[i] = 0;
            }
        }

        
		pKKContext->nAbtAlloc = pKKContext->nAbtCount = 0;
		pKKContext->pKKAbteilung = 0;
		pKKContext->pAktAbteilung = 0;
		pKKContext->lMBDSStatOk = 0;

		for (i = 0; i < MAX_BERICHT_TYP; i++)
			pKKContext->pBericht[i] = 0;

        if (fill_context_abteilungen (pContext, pContext->pCheckContext, pKKContext) == LKF_OUTOFMEMORY_ERROR) {
            lkf_free_kk_context(pKKContext);
            return 0;
        }
		return pKKContext;
	}
	else return 0;
}

static int bsearch_kk_abteilung (const void *cand, const void *elem) {
    const LKF_CONTEXT_ABTEILUNG *pAbt = *(const LKF_CONTEXT_ABTEILUNG **) elem;
    return strcmp ((const char *) cand, pAbt->sAbtFC);
}

LKF_KK_CONTEXT_ABTEILUNG *lkf_find_kk_abteilung (LKF_KK_CONTEXT *pKKContext, const char *sAbtFC)
{ /* V2019.1 */
    if (!pKKContext) {
        return 0;
    }
    return *(LKF_KK_CONTEXT_ABTEILUNG **) bsearch(sAbtFC, pKKContext->pKKAbteilung, pKKContext->nAbtCount, sizeof (LKF_KK_CONTEXT_ABTEILUNG *), bsearch_kk_abteilung);
    
}

LKF_KK_CONTEXT_ABTEILUNG *lkf_check_kk_abteilung (LKF_KK_CONTEXT *pKKContext, const char *sAbtFC, unsigned int bCreate)
{
	int nMin, nMax, nCur, nCmp;
	nMin = -1;
	nMax = (int) pKKContext->nAbtCount;

	while (nMin < nMax - 1)
	{
		nCur = (nMin + nMax) >> 1;
		nCmp = strncmp (pKKContext->pKKAbteilung[nCur].sAbtFC, sAbtFC, 8);
		if (nCmp)
		{
			if (nCmp > 0) nMax = nCur;
			else nMin = nCur;
		}
		else return pKKContext->pKKAbteilung + nCur;
	}

	if (bCreate)
	{
		LKF_KK_CONTEXT_ABTEILUNG *pKKAbt;

		LKF_KK_CONTEXT_ABTEILUNG *pAktAbteilung = pKKContext->pAktAbteilung;


		if (pKKContext->nAbtAlloc == pKKContext->nAbtCount)
		{
            LKF_CONTEXT *pContext;
			LKF_KK_CONTEXT_ABTEILUNG *pOld = pKKContext->pKKAbteilung;
            
            pContext = pKKContext->pContext;
            
			pKKContext->pKKAbteilung = LKF_CALLOC (pContext, "lkf_check_kk_abteilung", (pKKContext->nAbtAlloc += 10), sizeof (LKF_KK_CONTEXT_ABTEILUNG));
            if (!pKKContext->pKKAbteilung) {
                pKKContext->nAbtAlloc = pKKContext->nAbtCount = 0;
                if (pOld) LKF_FREE(pContext, "lkf_check_kk_abteilung", pOld);
                return 0;
            }
			if (pOld)
				memcpy (pKKContext->pKKAbteilung, pOld, sizeof(LKF_KK_CONTEXT_ABTEILUNG) * pKKContext->nAbtCount);
		
			if (pAktAbteilung) /* V18.0 */
 				pKKContext->pAktAbteilung = pAktAbteilung = pKKContext->pKKAbteilung + (pAktAbteilung - pOld);
		
			if (pOld) 
				LKF_FREE (pContext, "lkf_check_kk_abteilung", pOld); /* V18.0 */
		}
		if (nMax < (int) pKKContext->nAbtCount) /* V18.0 */ 
			memmove (pKKContext->pKKAbteilung + nMax + 1, pKKContext->pKKAbteilung + nMax, sizeof (LKF_KK_CONTEXT_ABTEILUNG) * (pKKContext->nAbtCount - (unsigned int) nMax));
		if (pAktAbteilung && (nMax <= (pAktAbteilung - pKKContext->pKKAbteilung))) 
			pKKContext->pAktAbteilung++;

		pKKContext->nAbtCount++;
		pKKAbt = pKKContext->pKKAbteilung + nMax;
		pKKAbt->pK01 = 0;
		pKKAbt->pK08 = 0;
		pKKAbt->pK09 = 0;
		pKKAbt->pK10 = 0;
		pKKAbt->pG01 = 0;
        pKKAbt->pA01 = 0;
		pKKAbt->nHasM02 = 0;
		pKKAbt->nHasM02Toleranz = 0;
		pKKAbt->nHasM02Jahr = 0;
		memcpy (pKKAbt->sAbtFC, sAbtFC, 8);
		pKKAbt->sAbtFC[8] = 0;
		pKKAbt->sIntKost[0] = 0;
		pKKAbt->nBelagstage = 0;
		pKKAbt->nVerbleibPat = 0;
		return pKKAbt;
	}
	else return 0;
}

int lkf_check_kk (LKF_CONTEXT *pContext, LKF_KK_CONTEXT *pKKContext)
{
    int ret;
	unsigned int i, j;
	unsigned int count;
	char sAbtFC[10];
	const LKF_SATZART_ERRORCHECK **ppGenKKChecks, *pCheck;
	const LKF_SATZART_ERRORCHECK **ppGenBerichtChecks;
	int has_kk, has_gg, has_kostplan;
	int has_b;

    
    ret = 0;
	has_kk = has_gg = 0;
	has_b = 0;

	has_kostplan = (pKKContext->pSatzartCount[0] > 0) ? 1 : 0;

	for (i = 1; !has_kk && i < MAX_K_SATZART_NUM; i++)
	{
		if (pKKContext->pSatzartCount[i] > 0) has_kk = 1;
	}

    for (i = 0; !has_b && i < MAX_B_SATZART_NUM; i++)
    {
        if (pKKContext->pBSatzartCount[i] > 0) has_b = 1;
    }

	for (i = 0; !has_gg && i < MAX_G_SATZART_NUM; i++)
	{
		if (pKKContext->pGGSatzartCount[i] > 0) has_gg = 1;
	}

	if (has_kostplan)
	{
		count = pKKContext->pSatzartCount[0];
		pKKContext->nCurrentCheckSatzart = i;


		if (lkf_isTraceInfo (pContext,LKF_FAC_KAS_KORE))
		{
			char sTraceLine[1024];
			sprintf (sTraceLine, "KAS-KORE-Ueberpruefung '%3.3s'", pKKContext->ppKKSatzarten[0]->pSatzart->sPrefix);
			lkf_addTraceLine (pContext->pCheckContext, sTraceLine, 0, LKF_TRACE_INFO);
		}
        
        if (pContext->modelljahr >= 2017) {
            
            const LKF_EXPANDED_LINE **expLines = pKKContext->pppExpandedLines[0];
            
            for (j = 0; j < count; j++) {
                Satzart_GetValueStringExp (expLines[j], pKKContext->ppKKSatzarten[0]->ppRef[GEN_ABTFC], sAbtFC, 10);
                pKKContext->pAktAbteilung = lkf_check_kk_abteilung (pKKContext, sAbtFC, 1);
                if (!pKKContext->pAktAbteilung) return LKF_OUTOFMEMORY_ERROR;
                Satzart_CheckExp (pContext, expLines[j], pKKContext->ppKKSatzarten[0], pContext->pCheckContext);
            }
            }
        else {
            for (j = 0; j < count; j++) {
                Satzart_GetValueString (pKKContext->pppSatzartRecords[0][j], pKKContext->ppSatzartRecordLen[0][j], pKKContext->ppKKSatzarten[0]->ppRef[GEN_ABTFC], sAbtFC, 10);
                pKKContext->pAktAbteilung = lkf_check_kk_abteilung (pKKContext, sAbtFC, 1);
                if (!pKKContext->pAktAbteilung) return LKF_OUTOFMEMORY_ERROR;
                Satzart_Check (pContext, pKKContext->pppSatzartRecords[0][j], pKKContext->ppKKSatzarten[0], pContext->pCheckContext);
            }
        }

	}
	else
	{
		if (lkf_isTraceInfo (pContext,LKF_FAC_KAS_KORE))
		{
			lkf_addTraceLine (pContext->pCheckContext, "kein Kostenstellenplan gemeldet, K01-Check wird ausgelassen", 0, LKF_TRACE_INFO);
		}
	}

	if (has_kk)
	{
		for (i = 1; i < MAX_K_SATZART_NUM; i++) 
		{
			count = pKKContext->pSatzartCount[i];
			pKKContext->nCurrentCheckSatzart = i;


			if (lkf_isTraceInfo (pContext,LKF_FAC_KAS_KORE))
			{
				char sTraceLine[1024];
				sprintf (sTraceLine, "KAS-KORE-Überprüfung '%3.3s'", pKKContext->ppKKSatzarten[i]->pSatzart->sPrefix);
				lkf_addTraceLine (pContext->pCheckContext, sTraceLine, 0, LKF_TRACE_INFO);
			}

            if (pContext->modelljahr >= 2017) {
                
                const LKF_EXPANDED_LINE **ppExpLines = pKKContext->pppExpandedLines[i];
                
                for (j = 0; j < count; j++) {
                    
                    if (i == 0 || i == 7 || i == 8 || i == 9)
                    {
                        Satzart_GetValueStringExp (ppExpLines[j], pKKContext->ppKKSatzarten[i]->ppRef[GEN_ABTFC], sAbtFC, 10);
                        pKKContext->pAktAbteilung = lkf_check_kk_abteilung (pKKContext, sAbtFC, 1);
                        if (!pKKContext->pAktAbteilung) return LKF_OUTOFMEMORY_ERROR;
                    }
                    else
                        pKKContext->pAktAbteilung = 0;
                    
                    
                    Satzart_CheckExp (pContext, ppExpLines[j], pKKContext->ppKKSatzarten[i], pContext->pCheckContext);
                }
            }
            else {
                for (j = 0; j < count; j++) {
                    
                    if (i == 0 || i == 7 || i == 8 || i == 9)
                    {
                        Satzart_GetValueString (pKKContext->pppSatzartRecords[i][j], pKKContext->ppSatzartRecordLen[i][j], pKKContext->ppKKSatzarten[i]->ppRef[GEN_ABTFC], sAbtFC, 10);
                        pKKContext->pAktAbteilung = lkf_check_kk_abteilung (pKKContext, sAbtFC, 1);
                        if (!pKKContext->pAktAbteilung) return LKF_OUTOFMEMORY_ERROR;

                    }
                    else
                        pKKContext->pAktAbteilung = 0;
                    
                    
                    Satzart_Check (pContext, pKKContext->pppSatzartRecords[i][j], pKKContext->ppKKSatzarten[i], pContext->pCheckContext);
                }
            }
		}
	}

	if (pContext->modelljahr >= 2014) lkf_checkL01 (pContext->pCheckContext); /* V17.0 - V17.1: erst ab 2014 */

	if (has_gg) 
	{
		for (i = 0; i < MAX_G_SATZART_NUM; i++)
		{
			count = pKKContext->pGGSatzartCount[i];
			pKKContext->nCurrentCheckSatzart = i;
            
            if (pContext->modelljahr >= 2017) {
                for (j = 0; j < count; j++) {
                    Satzart_CheckExp (pContext, pKKContext->pppGGExpandedLines[i][j], pKKContext->ppGGSatzarten[i], pContext->pCheckContext);
                }
            }
            else {
                for (j = 0; j < count; j++) {
                    Satzart_Check (pContext, pKKContext->pppGGSatzartRecords[i][j], pKKContext->ppGGSatzarten[i], pContext->pCheckContext);
                }
            }
		}
	}

    if (pContext->modelljahr >= SATZART_A_MODEL)
    {
        for (i = 0; i < MAX_A_SATZART_NUM; i++)
        {
            count = pKKContext->pASatzartCount[i];
            if (count > 0) {
                pKKContext->nCurrentCheckSatzart = i;
                for (j = 0; j < count; j++) {
                    Satzart_CheckExp (pContext, pKKContext->pppAExpandedLines[i][j], pKKContext->ppASatzarten[i], pContext->pCheckContext);
                }
            }
        }
    }

    
	ppGenKKChecks = lkf_get_facility_general_checks (pContext, LKF_FAC_KAS_KORE);
	pContext->pCheckContext->sErrorAdditionalInfo[0] = 0;
	i = 0;
	while ((pCheck = ppGenKKChecks[i]))
	{
		while (pCheck) 
		{
			pCheck = lkf_getModelDependentCheck (pCheck, pContext);

			if (pCheck)
			{
                ret = Satzart_ErrorCheckField (0, 0, 0, pCheck, pContext->pCheckContext);
                if (ret == LKF_OUTOFMEMORY_ERROR) return ret;
				if (ret) {
					Satzart_ReportError (pContext, pContext->pCheckContext, 0, 0, 0, 0, pCheck->pErrorDef, pContext->pCheckContext->sErrorAdditionalInfo);
					pContext->pCheckContext->sErrorAdditionalInfo[0] = 0;
					pCheck = pCheck->pNextErr;
				}
				else pCheck = pCheck->pNextSuc;
			}
		}
		++i;
	}


	if (has_b)
	{
		for (i = 0; i < MAX_B_SATZART_NUM; i++)
		{
			count = pKKContext->pBSatzartCount[i];
			pKKContext->nCurrentCheckSatzart = i;
            
            if (pContext->modelljahr >= 2017) {
                for (j = 0; j < count; j++) {
                    Satzart_CheckExp (pContext, pKKContext->pppBBExpandedLines[i][j], pKKContext->ppBSatzarten[i], pContext->pCheckContext);
                }
            }
            else {
                for (j = 0; j < count; j++) {
                    Satzart_Check (pContext, pKKContext->pppBSatzartRecords[i][j], pKKContext->ppBSatzarten[i], pContext->pCheckContext);
                }
            }
		}
	
		ppGenBerichtChecks = lkf_get_facility_general_checks (pContext, LKF_FAC_BERICHT);
		if (ppGenBerichtChecks)
		{
			i = 0;
			while ((pCheck = ppGenBerichtChecks[i]))
			{
				while (pCheck) 
				{
					pCheck = lkf_getModelDependentCheck (pCheck, pContext);

					if (pCheck)
					{
                        ret = Satzart_ErrorCheckField (0, 0, 0, pCheck, pContext->pCheckContext);
                        if (ret == LKF_OUTOFMEMORY_ERROR) return ret;
						if (ret) {
							Satzart_ReportError (pContext, pContext->pCheckContext, 0, 0, 0, 0, pCheck->pErrorDef, pContext->pCheckContext->sErrorAdditionalInfo);
							pContext->pCheckContext->sErrorAdditionalInfo[0] = 0;
							pCheck = pCheck->pNextErr;
						}
						else pCheck = pCheck->pNextSuc;
					}
				}
				++i;
			}
		}
	}
    return ret;
}

void lkf_free_kk_context (LKF_KK_CONTEXT *pKKContext)
{
	unsigned int i;    
	if (pKKContext)
	{
        LKF_CONTEXT *pContext = pKKContext->pContext;
        
		for (i = 0; i < MAX_K_SATZART_NUM; i++)
		{
			if (pKKContext->ppSatzartRecordLen[i]) LKF_FREE (pContext, "lkf_free_kk_context", pKKContext->ppSatzartRecordLen[i]);
			Satzart_GetLinesFree (pContext, pKKContext->pppSatzartRecords[i]);
			if (pKKContext->pppExpandedLines[i]) LKF_FREE (pContext, "lkf_free_kk_context", (void *)pKKContext->pppExpandedLines[i]);
		}
		if (pKKContext->pKKAbteilung) LKF_FREE (pContext, "lkf_free_kk_context", pKKContext->pKKAbteilung);

        for (i = 0; i < MAX_G_SATZART_NUM; i++)
        {
            if (pKKContext->ppGGSatzartRecordLen[i]) LKF_FREE (pContext, "lkf_free_kk_context", pKKContext->ppGGSatzartRecordLen[i]);
            Satzart_GetLinesFree (pContext, pKKContext->pppGGSatzartRecords[i]);
			if (pKKContext->pppGGExpandedLines[i]) LKF_FREE (pContext, "lkf_free_kk_context", pKKContext->pppGGExpandedLines[i]);
        }

        for (i = 0; i < MAX_A_SATZART_NUM; i++)
        {
            if (pKKContext->ppASatzartRecordLen[i]) LKF_FREE (pContext, "lkf_free_kk_context", pKKContext->ppASatzartRecordLen[i]);
            Satzart_GetLinesFree (pContext, pKKContext->pppASatzartRecords[i]);
            if (pKKContext->pppAExpandedLines[i]) LKF_FREE (pContext, "lkf_free_kk_context", pKKContext->pppAExpandedLines[i]);
        }
        
		for (i = 0; i < MAX_BERICHT_TYP; i++)
		{
			if (pKKContext->pBericht[i])
				LKF_FREE (pContext, "lkf_free_kk_context", pKKContext->pBericht[i]);
			if (pKKContext->pppBBExpandedLines[i]) LKF_FREE (pContext, "lkf_free_kk_context", pKKContext->pppBBExpandedLines[i]);
		}

		LKF_FREE (pContext, "lkf_free_kk_context", pKKContext);
	}
}

/******************************************************************************************
** lkf_alloc_errorgroup: Erzeugt die Error-Information für ein Modelljahr                **
******************************************************************************************/

LKF_ERRORGROUP *lkf_alloc_errorgroup (LKF_CONTEXT *pContext, const LKF_SATZART_ERRORDEF **ppErrors)
{
	unsigned int i, nSev;
	LKF_ERRORGROUP *pErrors;
	const LKF_SATZART_ERRORDEF *pErrorDef;
	pErrors = (LKF_ERRORGROUP *) LKF_MALLOC (pContext, "lkf_alloc_errorgroup", sizeof (LKF_ERRORGROUP));
    if (!pErrors) return 0;
    
	pErrors->errordef_count = 0;
	pErrors->errordefindex_count = 0;

	pErrors->min_error = pErrors->min_warning = 9999;
	pErrors->max_error = pErrors->max_warning = 0;
	
	for (i = 0; (pErrorDef = ppErrors[i]); i++) 
    {
		nSev = lkf_getSeverity (pContext, pErrorDef);
		if (nSev & LKF_SEV_ERROR) {
            if (pErrorDef->nCode > pErrors->errordefindex_count) pErrors->errordefindex_count = pErrorDef->nCode;
			if (pErrorDef->nCode < pErrors->min_error)	pErrors->min_error = pErrorDef->nCode;
			if (pErrorDef->nCode > pErrors->max_error)	pErrors->max_error = pErrorDef->nCode;
		}
		else if (nSev & LKF_SEV_WARNING) {
            if (pErrorDef->nCode + LKF_WARNING_OFFSET > pErrors->errordefindex_count) pErrors->errordefindex_count = pErrorDef->nCode + LKF_WARNING_OFFSET;
			if (pErrorDef->nCode < pErrors->min_warning)	pErrors->min_warning = pErrorDef->nCode;
			if (pErrorDef->nCode > pErrors->max_warning)	pErrors->max_warning = pErrorDef->nCode;
		}
	
	}
	pErrors->errordef_count = i;
	pErrors->ppErrorDef = ppErrors;
	if (pErrors->min_error == 9999) pErrors->min_error = 0;
    if (pErrors->min_warning == 9999) pErrors->min_warning = 0;

	if (pErrors->errordefindex_count) {
		pErrors->ppErrorDefIndex = (const LKF_SATZART_ERRORDEF **) LKF_CALLOC (pContext, "lkf_alloc_errorgroup.edi", pErrors->errordefindex_count + 1, sizeof (const LKF_SATZART_ERRORDEF *));
        if (!pErrors->ppErrorDefIndex) {
            LKF_FREE(pContext, "lkf_alloc_errorgroup", pErrors);
            return 0;
        }
	}
	else pErrors->ppErrorDefIndex = 0;

	for (i = 0; i < pErrors->errordef_count; i++) 
	{
		pErrorDef = ppErrors[i];
		nSev = lkf_getSeverity (pContext, pErrorDef);
		if (nSev & LKF_SEV_WARNING) {
            if (pErrorDef->nCode && !pErrors->ppErrorDefIndex[pErrorDef->nCode + LKF_WARNING_OFFSET])
                pErrors->ppErrorDefIndex[pErrorDef->nCode + LKF_WARNING_OFFSET] = pErrorDef;
		}
		else
		{
            if (pErrorDef->nCode && !pErrors->ppErrorDefIndex[pErrorDef->nCode])
                pErrors->ppErrorDefIndex[pErrorDef->nCode] = pErrorDef;
		}
	}

	return pErrors;
}

void lkf_free_errorgroup (LKF_CONTEXT *pContext, LKF_ERRORGROUP *pErrorGroup)
{
	if (pErrorGroup->ppErrorDefIndex) LKF_FREE (pContext, "lkf_free_errorgroup", pErrorGroup->ppErrorDefIndex);
	LKF_FREE (pContext, "lkf_free_errorgroup", pErrorGroup);
}



/**************************************************************************
** Routinen fuer Satzart-Error-Cache                                     **
**************************************************************************/

typedef struct 
{
	const LKF_SATZART_ERRORDEF *pErrorDef;
	LKF_SATZART_ERRORINFO_LIST *pList;
	unsigned int lErrorInfoIndex;
} ERRORDEF_CACHEITEM;

typedef struct {
	unsigned int nAlloc;
	unsigned int nCount;
	ERRORDEF_CACHEITEM *pCacheItems;
	LKF_CONTEXT *pContext;
} ERRORDEF_CACHE;

static ERRORDEF_CACHE *lkf_errordefcache_create (LKF_CONTEXT *pContext)
{
	ERRORDEF_CACHE *pCache;
	pCache = (ERRORDEF_CACHE *) LKF_MALLOC (pContext, "lkf_errordefcache_create", sizeof(ERRORDEF_CACHE));
    if (!pCache) return 0;
	pCache->nAlloc = 50;
	pCache->nCount = 0;
	pCache->pCacheItems = (ERRORDEF_CACHEITEM *) LKF_CALLOC (pContext, "lkf_errordefcache_create.items", pCache->nAlloc, sizeof(ERRORDEF_CACHEITEM));
    if (!pCache->pCacheItems) {
        LKF_FREE(pContext, "lkf_errordefcache_create", pCache);
        return 0;
    }
	pCache->pContext = pContext;
	return pCache;
}

static void lkf_errordefcache_free (ERRORDEF_CACHE *pCache)
{
	LKF_FREE (pCache->pContext, "lkf_errordefcache_free", pCache->pCacheItems);
	LKF_FREE (pCache->pContext, "lkf_errordefcache_free", pCache);
}

static ERRORDEF_CACHEITEM *lkf_errordefcache_get (ERRORDEF_CACHE *pCache, const LKF_SATZART_ERRORDEF *pErrorDef)
{
	int lMin, lMax, lCur, i;
	lMin = -1;
	lMax = (int) pCache->nCount;

    if (!pCache->pCacheItems) return 0;

	while (lMin + 1 < lMax) 
	{
		lCur = (lMin + lMax) / 2;
		if (pErrorDef < pCache->pCacheItems[lCur].pErrorDef) 
			lMax = lCur;
		else if (pErrorDef > pCache->pCacheItems[lCur].pErrorDef)
			lMin = lCur;
		else 
			return pCache->pCacheItems + lCur;
	}

	if (pCache->nAlloc == pCache->nCount) {
		ERRORDEF_CACHEITEM *pOld = pCache->pCacheItems;
		pCache->nAlloc += 50;
		pCache->pCacheItems = (ERRORDEF_CACHEITEM *) LKF_CALLOC (pCache->pContext, "lkf_errordefcache_get", pCache->nAlloc, sizeof (ERRORDEF_CACHEITEM));
        if (!pCache->pCacheItems) {
            pCache->nAlloc = pCache->nCount = 0;
            LKF_FREE (pCache->pContext, "lkf_errordefcache_get", pOld);
            return 0;
        }
		memcpy (pCache->pCacheItems, pOld, sizeof (ERRORDEF_CACHEITEM) * pCache->nCount);
		LKF_FREE (pCache->pContext, "lkf_errordefcache_get", pOld);
	}

	i = ((int) pCache->nCount) - lMax;

	if (i) memmove (pCache->pCacheItems + lMax + 1, pCache->pCacheItems + lMax, sizeof (ERRORDEF_CACHEITEM) * (unsigned int) i);
	pCache->pCacheItems[lMax].pErrorDef = pErrorDef;
	pCache->pCacheItems[lMax].pList = 0;
	pCache->pCacheItems[lMax].lErrorInfoIndex = 0;

	pCache->nCount++;
	return pCache->pCacheItems + lMax;
}

static int lkf_errorinfo_sort_function (const void *e1, const void *e2)
{	
	return memcmp (((LKF_SATZART_ERRORINFO *)e1)->sErrorCode, ((LKF_SATZART_ERRORINFO *)e2)->sErrorCode, 4);
}

void lkf_errorinfo_sort (LKF_SATZART_ERRORINFO_LIST *pList)
{
	qsort (pList->pErrors, pList->nCount, sizeof (LKF_SATZART_ERRORINFO), lkf_errorinfo_sort_function); 
}

/***************************************************************************
** lkf_errorinfo_add:                                                     **
**        Fügt einen Error dem Errorinfo-Cache hinzu oder liefert einen   **
**        bestehenden Eintrag zurück.                                     **
***************************************************************************/




static LKF_SATZART_ERRORINFO *lkf_errorinfo_add (LKF_SATZART_ERRORINFO_LIST *pList, ERRORDEF_CACHE *pCache, const LKF_SATZART_ERRORDEF *pErrorDef, int nFonds, int nNichtFonds)
{
	LKF_SATZART_ERRORINFO *pErrorInfo;
	ERRORDEF_CACHEITEM *pCacheItem;

	const LKF_SATZART_ERROR_PROPERTIES *pProperties;
	pProperties = lkf_getErrorProperties (pErrorDef, pList ? pList->pContext : 0);
	if (!pProperties->nFonds) nFonds = 0;
	if (!pProperties->nNichtFonds) nNichtFonds = 0;
	
	if (!nFonds && !nNichtFonds) return 0;

	pCacheItem = lkf_errordefcache_get (pCache, pErrorDef);
	
    if (!pCacheItem) {
        lkf_set_outOfMemory(pList->pContext, "lkf_errorinfo_add", 0);
        return 0;
    }
    
    
    if (pCacheItem->pList)
	{
        if (!pCacheItem->pList->pErrors || pCacheItem->lErrorInfoIndex == LKF_OUTOFMEMORY_UINTERROR) {
            return 0;
        }

		pErrorInfo = pCacheItem->pList->pErrors + pCacheItem->lErrorInfoIndex;
		pErrorInfo->nOccurrences++;	

		pErrorInfo->nFonds |= nFonds;
		pErrorInfo->nFonds |= nNichtFonds;

		return pErrorInfo;
	}
	else 
	{
		pCacheItem->pList = pList;	
        pCacheItem->lErrorInfoIndex = lkf_getNextFreeErrorInfo (pList);
        if (pCacheItem->lErrorInfoIndex == LKF_OUTOFMEMORY_UINTERROR) {
            return 0;
        }
		pErrorInfo = pList->pErrors + pCacheItem->lErrorInfoIndex;
		pErrorInfo->pError = pErrorDef;
		pErrorInfo->nOccurrences = 1;
		pErrorInfo->nAlloc = pErrorInfo->nCount = 0;
		pErrorInfo->pContext = pList->pContext;
		pErrorInfo->nFonds = nFonds;
		pErrorInfo->nNichtFonds = nNichtFonds;
		pErrorInfo->pUsage = 0;
        if (pErrorDef) {
            lkf_getErrorIdent (pList->pContext, pErrorDef, 6, pErrorInfo->sErrorCode);
        }
		return pErrorInfo;
	}
}

int find_errorinfo (const void *key, const void *cand) {
    return memcmp (key, ((LKF_SATZART_ERRORINFO *)cand)->sErrorCode, 4);
}

LKF_SATZART_ERRORINFO *lkf_errorinfo_increment (LKF_SATZART_ERRORINFO_LIST *pList, const LKF_SATZART_ERRORDEF *pErrorDef) {
    
    LKF_SATZART_ERRORINFO *pErrorInfo;
    char errorCode[6];
    lkf_getErrorIdent(pList->pContext, pErrorDef, 6, errorCode);
        
    pErrorInfo = (LKF_SATZART_ERRORINFO *) bsearch(errorCode, pList->pErrors, pList->nCount, sizeof(LKF_SATZART_ERRORINFO), find_errorinfo);
    
    if (pErrorInfo) {
        pErrorInfo->nOccurrences++;
        return pErrorInfo;
    }
    
    if (pList->nCount == pList->nAlloc) {
        LKF_SATZART_ERRORINFO *ppOld = pList->pErrors;
        pList->nAlloc += 100;
        pList->pErrors = (LKF_SATZART_ERRORINFO *) LKF_MALLOC (pList->pContext, "lkf_errorinfo_increment", sizeof(LKF_SATZART_ERRORINFO) * pList->nAlloc);
        if (!pList->pErrors) {
            LKF_FREE (pList->pContext, "lkf_errorinfo_increment", ppOld);
            return 0;
        }
        memcpy (pList->pErrors, ppOld, sizeof (LKF_SATZART_ERRORINFO) * pList->nCount);
        LKF_FREE (pList->pContext, "lkf_errorinfo_increment", ppOld);
    }
    
    pErrorInfo = pList->pErrors + pList->nCount++;
    
    pErrorInfo->pError = pErrorDef;
    pErrorInfo->nOccurrences = 1;
    pErrorInfo->nAlloc = pErrorInfo->nCount = 0;
    pErrorInfo->pContext = pList->pContext;
    pErrorInfo->nFonds = 0;
    pErrorInfo->nNichtFonds = 0;
    pErrorInfo->pUsage = 0;
    strcpy (pErrorInfo->sErrorCode, errorCode);

    lkf_errorinfo_sort(pList);
    
    return pErrorInfo;
}

/******************************************************************************************************************
** lkf_errorinfo_add_satzart:                                                                                    **
**          Fügt die Errors und Warnings eines Datensatzes zur Errorinfo-Liste hinzu.                            **
******************************************************************************************************************/

static int lkf_errorinfo_add_check (LKF_SATZART_ERRORINFO_LIST *pList, ERRORDEF_CACHE *pCache, const SATZART *pSatzart, unsigned int nSeverity, const SATZART_FELD *pFeld, const LKF_SATZART_ERRORCHECK *pCheck, int nFonds, int nNichtFonds)
{
    int ret;
	unsigned int nSev;
	LKF_SATZART_ERRORINFO *pErrorInfo;

	pCheck = lkf_getModelDependentCheck (pCheck, pCache->pContext);

	if (pCheck && pCheck->pErrorDef) {

		nSev = lkf_getSeverity (pCache->pContext, pCheck->pErrorDef);
		if (nSev & nSeverity) 
		{
			pErrorInfo = lkf_errorinfo_add (pList, pCache, pCheck->pErrorDef, nFonds, (pCheck->nFunction & LKF_CHECK_NURFONDSKA) ? 0 : nNichtFonds);
            if (!pErrorInfo) return  LKF_OUTOFMEMORY_ERROR;
			if (pFeld && (pList->nListOptions & LKF_ERRORFILTER_SHOWDETAILS)) lkf_errorinfo_add_usage (pErrorInfo, pCheck, pSatzart, pFeld);
		}
		
        if (pCheck != pCheck->pNextErr) {
            ret = lkf_errorinfo_add_check (pList, pCache, pSatzart, nSeverity, pFeld, pCheck->pNextErr, nFonds, nNichtFonds);
            if (ret) return ret;
        }
        if (pCheck != pCheck->pNextSuc) {
            ret = lkf_errorinfo_add_check (pList, pCache, pSatzart, nSeverity, pFeld, pCheck->pNextSuc, nFonds, nNichtFonds);
            if (ret) return ret;
        }
	}
    return 0;
}

const SATZART_FELD *lkf_getSatzartFeld (int nModelljahr, const SATZART_FELD *pFeld)
{
	while (pFeld && pFeld->nAltModelljahr && pFeld->nAltModelljahr <= nModelljahr)
		pFeld = pFeld->pAlternateDef;
	return pFeld;
}

static void lkf_errorinfo_add_satzart (LKF_SATZART_ERRORINFO_LIST *pList, ERRORDEF_CACHE *pCache, const SATZART *pSatzart, unsigned int nSeverity, int nFonds, int nNichtFonds)
{
	unsigned int i;
	const SATZART_FELD *pFeld;

	for (i = 0; i < pSatzart->nCount; i++) {
		pFeld = lkf_getSatzartFeld (pCache->pContext->modelljahr, pSatzart->Felder + i);
		if (pFeld)
			lkf_errorinfo_add_check (pList, pCache, pSatzart, nSeverity, pFeld, pFeld->pCheckInfo, nFonds, nNichtFonds);
	}

	if (pSatzart->pCheck) lkf_errorinfo_add_check (pList, pCache, pSatzart, nSeverity, 0, pSatzart->pCheck, nFonds, nNichtFonds);
}

/***************************************************************************
** Routinen zum Aufbau der KASKORE-Satzarten                              **
***************************************************************************/

/***************************************************************************
** Routinen zum Aufbau der Berichtswesen-Satzarten                        **
***************************************************************************/

const SATZART_INFO **lkf_get_satzartFacility (LKF_CONTEXT *pContext, unsigned int facility, unsigned int *nCount) {
    
    if (!pContext->pSatzartDefs) {
        return 0;
    }
    
    switch (facility) {
        case LKF_FAC_BERICHT:
            if (nCount) *nCount = MAX_B_SATZART_NUM;
            return pContext->pSatzartDefs->ppB;
        case LKF_FAC_A:
            if (nCount) *nCount = MAX_A_SATZART_NUM;
            return pContext->pSatzartDefs->ppA;
        case LKF_FAC_GG:
            if (nCount) *nCount = MAX_G_SATZART_NUM;
            return pContext->pSatzartDefs->ppG;
        case LKF_FAC_KAS_KORE:
            if (nCount) *nCount = MAX_K_SATZART_NUM;
            return pContext->pSatzartDefs->ppK;
        default:
            return 0;
    }    
}

int lkf_create_facility_errorinfo (LKF_SATZART_ERRORINFO_LIST *pList, LKF_CONTEXT *pContext, unsigned int nFacility, unsigned int nSeverity)
{ /* V14.2 */
    unsigned int i;
    const SATZART_INFO **ppSatzarten;
    const LKF_SATZART_ERRORCHECK **ppChecks;
    const LKF_SATZART_ERRORDEF **ppErrors;
    ERRORDEF_CACHE *pErrorCache;
    unsigned int satzartCount;
    
    if (!pContext->pSatzartDefs) {
        pContext->pSatzartDefs = lkf_Satzart_getDefinition(pContext->modelljahr);
    }
    
    ppSatzarten = lkf_get_satzartFacility(pContext, nFacility, &satzartCount);
    
    if (!ppSatzarten) {
        return -1;
    }

    pErrorCache = lkf_errordefcache_create (pContext);
    if (!pErrorCache) return LKF_OUTOFMEMORY_ERROR;
    
    for (i = 0; i <= satzartCount; i++) {
        if (ppSatzarten[i]) {
            lkf_errorinfo_add_satzart (pList, pErrorCache, ppSatzarten[i]->pSatzart, nSeverity, 1, 1);

        }
    }
    ppChecks = lkf_get_facility_general_checks (pList->pContext, nFacility);
    if (ppChecks) {
        i = 0;
        while (ppChecks[i])
        {
            lkf_errorinfo_add_check (pList, pErrorCache, 0, nSeverity, 0, ppChecks[i++], 1, 1);
        }
    }
    
    
    ppErrors = lkf_get_general_errors (pList->pContext, nFacility);
    
    if (ppErrors) {
        unsigned int nErrorSeverity;
        i = 0;
        while (ppErrors[i])
        {
            nErrorSeverity = lkf_getSeverity (pContext, ppErrors[i]);
            if (nErrorSeverity & nSeverity)
            {
                lkf_errorinfo_add (pList, pErrorCache, ppErrors[i], 1, 1);
            }
            ++i;
        }
    }
    lkf_errordefcache_free (pErrorCache);
    return 0;
}


/***************************************************************************
** Routinen zum Aufbau der Int-Scoring-Errorinfo                          **
***************************************************************************/
extern const SATZART Int01, Int02, Int03, Int11, Int12;

int lkf_create_intscoring_errorinfo (LKF_SATZART_ERRORINFO_LIST *pList, LKF_CONTEXT *pContext, unsigned int nSeverity)
{
	unsigned int nSev;
	ERRORDEF_CACHE *pIntErrorCache;
	const LKF_SATZART_ERRORDEF **ppGeneralErrors, *pError;
	unsigned int i;
	ppGeneralErrors = lkf_GetGeneralIntScoringErrors (pContext->modelljahr);
	pIntErrorCache = lkf_errordefcache_create (pContext);

    if (!pIntErrorCache) {
        return LKF_OUTOFMEMORY_ERROR;
    }
    
	i = 0;
	while (ppGeneralErrors[i]) 
	{
		pError = ppGeneralErrors[i++];
		nSev = lkf_getSeverity (pContext, pError);
        if (nSev & nSeverity) lkf_errorinfo_add (pList, pIntErrorCache, pError, 1, (pContext->modelljahr >= 2014)?1:0);
	}

	if (pContext->modelljahr >= 2012)
	{
		lkf_errorinfo_add_satzart (pList, pIntErrorCache, &Int11, nSeverity, 1, 1);
		lkf_errorinfo_add_satzart (pList, pIntErrorCache, &Int12, nSeverity, 1, 1);
	}
	else
	{
		lkf_errorinfo_add_satzart (pList, pIntErrorCache, &Int01, nSeverity, 1, 0);
		lkf_errorinfo_add_satzart (pList, pIntErrorCache, &Int02, nSeverity, 1, 0);
		lkf_errorinfo_add_satzart (pList, pIntErrorCache, &Int03, nSeverity, 1, 0);

		if (pContext->modelljahr == 2011)
		{
			lkf_errorinfo_add_satzart (pList, pIntErrorCache, &Int11, nSeverity, 1, 0);
			lkf_errorinfo_add_satzart (pList, pIntErrorCache, &Int12, nSeverity, 1, 0);
		}
	}

	lkf_errordefcache_free (pIntErrorCache);
    return 0;
}



/***************************************************************************
** Routinen zum Handling der Errorinfo-Struktur                           **
***************************************************************************/

LKF_SATZART_ERRORINFO_LIST *lkf_alloc_errorinfo (LKF_CONTEXT *pContext, unsigned int nListOptions)
{
	LKF_SATZART_ERRORINFO_LIST *pList;
	pList = (LKF_SATZART_ERRORINFO_LIST *) LKF_MALLOC (pContext, "lkf_alloc_errorinfo", sizeof (LKF_SATZART_ERRORINFO_LIST));
    if (!pList) return 0;
	pList->nAlloc = 100;
	pList->nCount = 0;
	pList->pErrors = (LKF_SATZART_ERRORINFO *) LKF_CALLOC (pContext, "lkf_alloc_errorinfo", pList->nAlloc, sizeof (LKF_SATZART_ERRORINFO));
    if (!pList->pErrors) {
        LKF_FREE(pContext, "lkf_alloc_errorinfo", pList);
        return 0;
    }
	pList->nListOptions = nListOptions;
	pList->pContext = pContext;
	return pList;
}

_SCORING_EXPORT void lkf_free_errorinfo (LKF_SATZART_ERRORINFO_LIST *pList)
{
	unsigned int i;
	LKF_SATZART_ERRORINFO *pErrorInfo;

	for (i = 0; i < pList->nCount; i++) 
	{
		pErrorInfo = pList->pErrors + i;
		if (pErrorInfo->pUsage) LKF_FREE (pList->pContext, "lkf_free_errorinfo", pErrorInfo->pUsage);
	}
	LKF_FREE (pList->pContext, "lkf_free_errorinfo", pList->pErrors);
	LKF_FREE (pList->pContext, "lkf_free_errorinfo", pList);
}

unsigned int lkf_getNextFreeErrorInfo (LKF_SATZART_ERRORINFO_LIST *pList)
{
	if (pList->nAlloc == pList->nCount) {
		LKF_SATZART_ERRORINFO *pOld = pList->pErrors;
		pList->nAlloc += 100;
		pList->pErrors = LKF_CALLOC (pList->pContext, "lkf_getNextFreeErrorInfo", sizeof (LKF_SATZART_ERRORINFO), pList->nAlloc);
        if (!pList->pErrors) {
            pList->nAlloc = pList->nCount = 0;
            return LKF_OUTOFMEMORY_UINTERROR;
        }
		if (pOld) {
			memcpy (pList->pErrors, pOld, pList->nCount * sizeof (LKF_SATZART_ERRORINFO));
			LKF_FREE (pList->pContext, "lkf_getNextFreeErrorInfo", pOld);
		}
	}
	return pList->nCount++;
}

int lkf_errorinfo_add_usage (LKF_SATZART_ERRORINFO *pErrorInfo, const LKF_SATZART_ERRORCHECK *pCheck, const SATZART *pSatzart, const SATZART_FELD *pFeld)
{
	LKF_SATZART_ERRORINFO_USAGE *pUsage;
	unsigned int i;

	for (i = 0; i < pErrorInfo->nCount; i++) 
	{
		pUsage = pErrorInfo->pUsage + i;
		if (pUsage->pErrorCheck == pCheck && pUsage->pFeld == pFeld && pUsage->pSatzart == pSatzart)
			return 0;
	}

	if (pErrorInfo->nCount == pErrorInfo->nAlloc) 
	{
		pUsage = pErrorInfo->pUsage;
		pErrorInfo->nAlloc += 5;
		pErrorInfo->pUsage = (LKF_SATZART_ERRORINFO_USAGE *) LKF_CALLOC (pErrorInfo->pContext, "lkf_errorinfo_add_usage", sizeof (LKF_SATZART_ERRORINFO_USAGE), pErrorInfo->nAlloc);
		
        if (!pErrorInfo->pUsage) {
            if (pUsage) LKF_FREE (pErrorInfo->pContext, "lkf_errorinfo_add_usage", pUsage);
            pErrorInfo->nCount = pErrorInfo->nAlloc = 0;
            return LKF_OUTOFMEMORY_ERROR;
        }
        
        if (pUsage && pErrorInfo->nCount)
			memcpy (pErrorInfo->pUsage, pUsage, sizeof (LKF_SATZART_ERRORINFO_USAGE) * pErrorInfo->nCount);
        if (pUsage) LKF_FREE (pErrorInfo->pContext, "lkf_errorinfo_add_usage", pUsage);
	}

	pUsage = pErrorInfo->pUsage + pErrorInfo->nCount++;
	pUsage->pErrorCheck = pCheck;
	pUsage->pFeld = pFeld;
	pUsage->pSatzart = pSatzart;
	return 1;
}

/******************************************************************************************************************
** lkf_create_plauserrorinfo:                                                                                    **
**          Erzeugt die Error-Info-Struktur für die MBDS-Errors und -Warnings.                                   **
******************************************************************************************************************/

static int lkf_create_plauserrorinfo (LKF_SATZART_ERRORINFO_LIST *pList, const LKF_SATZART_ERRORDEF **ppAllErrors, unsigned int nListOptions)
{
	unsigned int nSev;
	LKF_SATZART_ERRORINFO *pErrorInfo;
	const LKF_SATZART_ERRORDEF *pErrorDef;
	unsigned int i = 0;
	int bInclude;
	const LKF_SATZART_ERROR_PROPERTIES *pErrorProperties = 0;
	
	while (ppAllErrors[i]) 
	{
		pErrorDef = ppAllErrors[i++];
        
        while (pErrorDef && pErrorDef->pProperties && pErrorDef->pProperties->nAlternateErrorModelljahr && pErrorDef->pProperties->nAlternateErrorModelljahr && pErrorDef->pProperties->nAlternateErrorModelljahr <= pList->pContext->modelljahr) {
            pErrorDef = pErrorDef->pProperties->pAlternateError;
        }
        
        if (!pErrorDef) {
            continue;
        }

		bInclude = 0;
		nSev = lkf_getSeverity (pList->pContext, pErrorDef);
		if (nSev == LKF_SEV_ERROR || nSev == LKF_SEV_FATAL) 
		{
			if (nListOptions & LKF_ERRORFILTER_MBDSERROR) bInclude = 1;
		}
		else if (nListOptions & LKF_ERRORFILTER_MBDSWARNING) bInclude = 1;

		if (bInclude)
		{ /* V12.0 */
			pErrorProperties = lkf_getErrorProperties (pErrorDef, pList->pContext); /* V10.1 */
			if (pErrorProperties->nFonds == 0 && pErrorProperties->nNichtFonds == 0)
				bInclude = 0;
		}

		if (bInclude)
		{
			unsigned int nNextInfo = lkf_getNextFreeErrorInfo (pList);
            if (nNextInfo == LKF_OUTOFMEMORY_UINTERROR) {
                return 0;
            }
			pErrorInfo = pList->pErrors + nNextInfo;
			pErrorInfo->nAlloc = pErrorInfo->nCount = 0;
			pErrorInfo->pUsage = 0;
			pErrorInfo->pError = pErrorDef;
			pErrorInfo->nOccurrences = 1;
			pErrorInfo->nFonds = pErrorProperties->nFonds;
			pErrorInfo->nNichtFonds = pErrorProperties->nNichtFonds;
			pErrorInfo->pContext = pList->pContext;
			if (pErrorDef) lkf_getErrorIdent (pList->pContext, pErrorDef, 6, pErrorInfo->sErrorCode);
		}
	}
    return 0;
}

/******************************************************************************************************************
** lkf_create_errorinfo:                                                                                         **
**          Erzeugt die Error-Info-Struktur.                                                                     **
******************************************************************************************************************/

static int compareErrors (const void *err1, const void *err2) {
    
    const LKF_SATZART_ERRORINFO *pErrorInfo1, *pErrorInfo2;
    
    pErrorInfo1 = (const LKF_SATZART_ERRORINFO *) err1;
    pErrorInfo2 = (const LKF_SATZART_ERRORINFO *) err2;
    
    return strcmp (pErrorInfo1->sErrorCode, pErrorInfo2->sErrorCode);
}


_SCORING_EXPORT LKF_SATZART_ERRORINFO_LIST *lkf_create_errorinfo (LKF_CONTEXT *pContext, unsigned int nListOptions)
{
    int ret;
	const LKF_SATZART_ERRORDEF **ppAllErrors;
	LKF_SATZART_ERRORINFO_LIST *pList = lkf_alloc_errorinfo (pContext, nListOptions);
    if (!pList) return 0;
    
	if (pContext->modelljahr >= 2004)
	{

		if (nListOptions & LKF_ERRORFILTER_GENERALERROR)
		{
			ret = lkf_create_general_errorinfo (pList, pContext, LKF_SEV_ERROR | LKF_SEV_FATAL);
            if (ret == LKF_OUTOFMEMORY_ERROR) {
                return 0;
            }
		}

		if (nListOptions & LKF_ERRORFILTER_GENERALWARNING)
		{
			ret = lkf_create_general_errorinfo (pList, pContext, LKF_SEV_INFO | LKF_SEV_WARNING);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}


		if (nListOptions & LKF_ERRORFILTER_MBDSERROR) 
		{
			ppAllErrors = GetAllMBDSErrors (pContext->modelljahr);
			ret = lkf_create_plauserrorinfo (pList, ppAllErrors, LKF_ERRORFILTER_MBDSERROR);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

		if (nListOptions & LKF_ERRORFILTER_MBDSWARNING)
		{
			ppAllErrors = GetAllMBDSErrors (pContext->modelljahr);
			ret = lkf_create_plauserrorinfo (pList, ppAllErrors, LKF_ERRORFILTER_MBDSWARNING);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

		if (nListOptions & LKF_ERRORFILTER_KASKOREERROR) 
		{
			ret = lkf_create_facility_errorinfo (pList, pContext, LKF_FAC_KAS_KORE, LKF_SEV_ERROR | LKF_SEV_FATAL);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

		if (nListOptions & LKF_ERRORFILTER_KASKOREWARNING)
		{
            ret = lkf_create_facility_errorinfo (pList, pContext, LKF_FAC_KAS_KORE, LKF_SEV_INFO | LKF_SEV_WARNING);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

		if (nListOptions & LKF_ERRORFILTER_BERICHTERROR)
		{
            ret = lkf_create_facility_errorinfo (pList, pContext, LKF_FAC_BERICHT, LKF_SEV_ERROR | LKF_SEV_FATAL);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

        if (nListOptions & LKF_ERRORFILTER_AERROR) {
            ret = lkf_create_facility_errorinfo (pList, pContext, LKF_FAC_A, LKF_SEV_ERROR | LKF_SEV_FATAL);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
        }
        
		if (nListOptions & LKF_ERRORFILTER_BERICHTWARNING)
		{
            ret = lkf_create_facility_errorinfo (pList, pContext, LKF_FAC_BERICHT, LKF_SEV_INFO | LKF_SEV_WARNING);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

		if (nListOptions & LKF_ERRORFILTER_INTSCORERROR)
		{
			ret = lkf_create_intscoring_errorinfo (pList, pContext, LKF_SEV_ERROR | LKF_SEV_FATAL);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

		if (nListOptions & LKF_ERRORFILTER_INTSCORWARNING)
		{
			ret = lkf_create_intscoring_errorinfo (pList, pContext, LKF_SEV_INFO | LKF_SEV_WARNING);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

		if (nListOptions & LKF_ERRORFILTER_GGERROR)
		{
            ret = lkf_create_facility_errorinfo (pList, pContext, LKF_FAC_GG, LKF_SEV_ERROR | LKF_SEV_FATAL);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}

		if (nListOptions & LKF_ERRORFILTER_GGWARNING)
		{
            ret = lkf_create_facility_errorinfo (pList, pContext, LKF_FAC_GG, LKF_SEV_INFO | LKF_SEV_WARNING);
            if (ret == LKF_OUTOFMEMORY_ERROR) return 0;
		}
	}
    
    qsort(pList->pErrors, pList->nCount, sizeof (LKF_SATZART_ERRORINFO), compareErrors);
	return pList;
}

/****************************************************************************************************
** Routinen zum Auslesen der Errorinfo-Struktur                                                    **
****************************************************************************************************/

_SCORING_EXPORT unsigned int lkf_errorinfo_getCount (const LKF_SATZART_ERRORINFO_LIST *pList)
{
	return pList->nCount;
}

_SCORING_EXPORT const LKF_SATZART_ERRORINFO *lkf_errorinfo_getError (const LKF_SATZART_ERRORINFO_LIST *pList, unsigned int i)
{
	if (i < pList->nCount) return pList->pErrors + i;
	else return 0;
}

_SCORING_EXPORT unsigned int lkf_errorinfo_getErrorUsageCount (const LKF_SATZART_ERRORINFO *pErrorInfo)
{
	return pErrorInfo->nCount;
}

_SCORING_EXPORT LKF_SATZART_ERRORINFO_USAGE *lkf_errorinfo_getErrorUsage (const LKF_SATZART_ERRORINFO *pErrorInfo, unsigned int i)
{
	if (i < pErrorInfo->nCount) return pErrorInfo->pUsage + i;
	else return 0;
}

static unsigned int tobuf (const char *srcbuf, char *buf, unsigned int buflen)
{
	unsigned int cb, l = (unsigned int) strlen (srcbuf);
	cb = (l >= buflen) ? buflen - 1 : l;
	strncpy (buf, srcbuf, cb);
	buf[cb] = 0;
	return l + 1;
}


_SCORING_EXPORT unsigned int lkf_errorinfo_getHeadline (const LKF_SATZART_ERRORINFO_LIST *pList, char *buf, unsigned int buflen)
{
	return tobuf("CODE ; FACILITY ; SEVERITY   ; FONDS ; NFONDS ; ZUSATZINFO ; TEXT ; WERT", buf, buflen);
}

static const char *lkf_errorinfo_getFacilityText (unsigned int nFacility)
{
	switch (nFacility) {
		default:
		case LKF_FAC_ALL:
			return "";
		case LKF_FAC_MBDS:
			return "MBDS";
		case LKF_FAC_INTSCOR:
			return "IntScor";
		case LKF_FAC_KAS_KORE:
			return "KAS-KORE";
		case LKF_FAC_GG:
			return "GG";
		case LKF_FAC_BERICHT:
			return "BERICHT";
        case LKF_FAC_A:
            return "ANTIINFEKTIVA";
	}
}

static const char *lkf_errorinfo_getSeverityText (unsigned int nSeverity)
{
	switch (nSeverity) {
		case LKF_SEV_FATAL:
			return "FATAL";
		case LKF_SEV_ERROR:
			return "ERROR";
		case LKF_SEV_WARNING:
			return "WARNING";
		case LKF_SEV_WARNING_KORR:
			return "WARNING(K)";
		case LKF_SEV_INFO:
			return "INFO";
		default:
			return "";
	}
}

static char *lkf_errorinfo_getAddInfo (const LKF_CONTEXT *pContext, const LKF_SATZART_ERRORDEF *pErrorDef, char *buf)
{
	unsigned int nSev;
	*buf = 0;
	if (pErrorDef->nFacility == LKF_FAC_MBDS && pErrorDef->nOldCode > 0) {
		nSev = lkf_getSeverity (pContext, pErrorDef);
		if (nSev == LKF_SEV_ERROR) {
			sprintf (buf, "E%02d", pErrorDef->nOldCode);
		}
		else if (nSev & LKF_SEV_WARNING) {
			sprintf (buf, "W%02d", pErrorDef->nOldCode);
		}
	}
	return buf;
}


_SCORING_EXPORT unsigned int lkf_errorinfo_getErrorLine (const LKF_SATZART_ERRORINFO *pErrorInfo, char *buf, unsigned int buflen)
{
	const LKF_SATZART_ERRORDEF *pErrorDef;
	char localbuf[1024];
    char errorTextBuf[256];
	char errorident [5], addinfobuf[20];
	char cAccepted; /* V13.1 */

	pErrorDef = pErrorInfo->pError;
	cAccepted = (pErrorInfo->pError && (pErrorInfo->pError->nSeverity & LKF_SEV_ACCEPTABLE)) ? 'A' : 'X';
	lkf_getErrorIdent (pErrorInfo->pContext, pErrorDef, 5, errorident);
	sprintf (localbuf, "%4.4s;%-8.8s;%-10.10s;%c;%c;%-10.10s;%s;%s",
					   errorident, lkf_errorinfo_getFacilityText (pErrorDef->nFacility),
					   lkf_errorinfo_getSeverityText (lkf_getSeverity (pErrorInfo->pContext, pErrorDef)),
					   pErrorInfo->nFonds ? cAccepted : ' ',
					   pErrorInfo->nNichtFonds ? cAccepted : ' ',
					   lkf_errorinfo_getAddInfo (pErrorInfo->pContext, pErrorDef, addinfobuf),
					   lkf_context_formatted_text (pErrorInfo->pContext, pErrorDef->sText, errorTextBuf),
					   lkf_plaus_get_error_valuefield_description(pErrorInfo->pContext, pErrorInfo->pError));
	return tobuf (localbuf, buf, buflen);
}



_SCORING_EXPORT unsigned int lkf_errorinfo_getErrorUsageLine (const LKF_SATZART_ERRORINFO_USAGE *pErrorUsage, char *buf, unsigned int buflen)
{
	char localbuf [1024];
	sprintf (localbuf, "     ; ***      ; Satzart: %s, Feld: %s", pErrorUsage->pSatzart->sPrefix, pErrorUsage->pFeld->sFeldName);
	return tobuf (localbuf, buf, buflen);
}

LKF_CHECK_CONTEXT *lkf_alloc_checkcontext (LKF_CONTEXT *pContext)
{
	LKF_CHECK_CONTEXT *pCheckContext = (LKF_CHECK_CONTEXT *) LKF_MALLOC (pContext, "lkf_alloc_checkcontext", sizeof (LKF_CHECK_CONTEXT));
	if (pCheckContext == 0) return 0;

	pCheckContext->pAufenthalt = 0;
	pCheckContext->pContext = pContext;
	pCheckContext->nAbtIndex = -1;
	pCheckContext->pKKContext = 0;      /* V14.0 */
	pCheckContext->bKKTraceDetail = 0;  /* V14.0 */
	pCheckContext->bKKTraceInfo = 0;    /* V14.0 */
	pCheckContext->nTraceFacility = 0;  /* V14.0 */
	pCheckContext->sBerichtsTyp[0] = 0; /* V14.2 */
	pCheckContext->pCurrentCheck = 0; /* V2025.1 */
	return pCheckContext;
}

void lkf_free_checkcontext (LKF_CONTEXT *pContext, LKF_CHECK_CONTEXT *pCheckContext)
{
	if (pCheckContext) LKF_FREE (pContext, "lkf_free_checkcontext", pCheckContext);
}

LKF_CHECK_CONTEXT *lkf_get_contextcheckcontext (LKF_CONTEXT *pContext)
{
	if (!pContext->pCheckContext) {
		pContext->pCheckContext = lkf_alloc_checkcontext(pContext);
	}
	return pContext->pCheckContext;
}

/* Error-Handling für strukturierte Satzarten */

LKF_SATZART_ERRORS *Satzart_AllocErrorStructure(LKF_CONTEXT *pContext)
{
	LKF_SATZART_ERRORS *pErrors = (LKF_SATZART_ERRORS *) LKF_CALLOC (pContext, "Satzart_AllocErrorStructure", 1, sizeof (LKF_SATZART_ERRORS));
    if (!pErrors) return 0;
	pErrors->nAlloc = LKF_SATZART_ERRORS_INITIAL;
    if (pErrors->nAlloc) {
        pErrors->pErrors = (LKF_SATZART_ERROR *) LKF_CALLOC (pContext, "Satzart_AllocErrorStructure", pErrors->nAlloc, sizeof (LKF_SATZART_ERROR));
        if (!pErrors->pErrors) {
            LKF_FREE(pContext, "Satzart_AllocErrorStructure", pErrors);
            return 0;
        }
    }
	return pErrors;
}

void Satzart_FreeErrorStructure(LKF_CONTEXT *pContext, LKF_SATZART_ERRORS *pErrors)
{
	if (pErrors) {
		if (pErrors->pErrors) LKF_FREE (pContext, "Satzart_FreeErrorStructure", pErrors->pErrors);
		LKF_FREE (pContext, "Satzart_FreeErrorStructure", pErrors);
	}
}

LKF_SATZART_ERROR *Satzart_GetSatzartError (LKF_SATZART_ERRORS *pErrors, int index)
{
	if (index >= 0) return pErrors->pErrors + index;
	else return 0;
}

unsigned int Satzart_GetNextFreeErrorIndex (LKF_CONTEXT *pContext, LKF_SATZART_ERRORS *pErrors)
{
    if (!pErrors) return LKF_OUTOFMEMORY_UINTERROR;
	if (pErrors->nAlloc == pErrors->nCount) {
		LKF_SATZART_ERROR *pOld = pErrors->pErrors;

		if (LKF_SATZART_ERRORS_ADD * 5 < pErrors->nAlloc) pErrors->nAlloc += pErrors->nAlloc / 5;
		else pErrors->nAlloc += LKF_SATZART_ERRORS_ADD;
		
		pErrors->pErrors = (LKF_SATZART_ERROR *) LKF_CALLOC (pContext, "Satzart_GetNextFreeErrorIndex", pErrors->nAlloc, sizeof(LKF_SATZART_ERROR));
        if (!pErrors->pErrors) {
            if (pOld) LKF_FREE (pContext, "Satzart_GetNextFreeErrorIndex", pOld);
            pErrors->nAlloc = pErrors->nCount = 0;
            return LKF_OUTOFMEMORY_UINTERROR;
        }
        if (pOld) memcpy (pErrors->pErrors, pOld, sizeof (LKF_SATZART_ERROR) * pErrors->nCount);
		LKF_FREE (pContext, "Satzart_GetNextFreeErrorIndex", pOld);
	}
	return pErrors->nCount++;
}

_SCORING_EXPORT unsigned int lkf_getSatzartErrorCount (const LKF_CONTEXT *pContext)
{
	if (!pContext->pSatzartErrors) return 0;
	else if (pContext->ppFilteredErrors) return pContext->nFilteredErrors;
	else return pContext->pSatzartErrors->nCount;
}
	
	static const char facilityChars[] = {'A', 'X', 'I', 'K', 'G', 'B', 'A'};
	
	static const char hexchars[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
									'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'K', 'L',
									'M', 'N', 'P', 'Q', 'R', 'T', 'U', 'V', 'W', 'X', 
									'Y', 'Z'};

static unsigned int hextonum (char c)
{
	if (c >= '0' && c <= '9') return (unsigned int) (c - '0');
	else if (c <= 'H') return (unsigned int) (c - 'A' + 10);
	else if (c <= 'N') return (unsigned int) (c - 'K' + 18);
	else if (c <= 'R') return (unsigned int) (c - 'P' + 22);
	else return (unsigned int) (c - 'T' + 25);
}

_SCORING_EXPORT unsigned int lkf_getErrorIntFromCode (const char *errorcode)
{
	return hextonum (errorcode[0]) * 32 + hextonum (errorcode[1]);
}

_SCORING_EXPORT const char *lkf_getErrorCodeFromInt (unsigned int code, char *errorbuffer)
{
	errorbuffer[2] = 0;
	errorbuffer[0] = hexchars[code/32];
	errorbuffer[1] = hexchars[code%32];
	return errorbuffer;
}


const char *lkf_getErrorIdent (const LKF_CONTEXT *pContext, const LKF_SATZART_ERRORDEF *pErrorDef, unsigned int buflen, char *buf)
{ /* must work with pContext = 0 ! */

    char cs, fac;
	switch (lkf_getSeverity (pContext, pErrorDef)) 
	{
		case LKF_SEV_FATAL:
			cs = 'F'; break;
		case LKF_SEV_ERROR:
			cs = 'E'; break;
		case LKF_SEV_WARNING:
		case LKF_SEV_WARNING_KORR:
			cs = 'W'; break;
		case LKF_SEV_INFO:
			cs = 'H'; break;
		default:
			cs = '?'; break;
	}
    
    fac = facilityChars[pErrorDef->nFacility];
    if (fac == 'X' && pContext && pContext->modelljahr < 2017)
    {
        fac = 'M';
    }
    
	if (buflen > 4) {
		sprintf (buf, "%c%c%c%c", cs, fac, hexchars[pErrorDef->nCode/32], hexchars[pErrorDef->nCode%32]);
		return buf;
	}
	else return 0;
}


_SCORING_EXPORT int lkf_setErrorFormat (LKF_CONTEXT *pContext, unsigned int facility, unsigned int count, const unsigned int *fields)
{
	int i;
	LKF_CONTEXT_ERRORFORMAT *pErrorFormat;
    if (facility > LKF_FAC_ALLOC) return -1;
    else if (facility == LKF_FAC_ALLOC) {
        for (i = 0; i < LKF_FAC_ALLOC; i++) {
            pErrorFormat = pContext->pErrorFormats[i];
            if (pErrorFormat != 0) {
                if (pErrorFormat->fields) LKF_FREE (pContext, "lkf_setErrorFormat", pErrorFormat->fields);
                LKF_FREE(pContext, "lkf_setErrorFormat", pErrorFormat);
                pContext->pErrorFormats[i] = 0;
            }
        }
    }
    else {
        pErrorFormat = pContext->pErrorFormats[facility];
        if (pErrorFormat) {
            if (pErrorFormat->fields) LKF_FREE (pContext, "lkf_setErrorFormat", pErrorFormat->fields);
			LKF_FREE(pContext, "lkf_setErrorFormat", pErrorFormat);
			pContext->pErrorFormats[facility] = 0;
        }
    }
    if (count == 0) {
        return -2;
    }
    else {
        unsigned int i, minFacility, maxFacility;
        
        if (facility == LKF_FAC_ALLOC) {
            minFacility = 0;
            maxFacility = facility - 1;
        }
        else {
            minFacility = maxFacility = facility;
        }
        
        for (i = minFacility; i <= maxFacility; i++) {
            pErrorFormat = (LKF_CONTEXT_ERRORFORMAT *) LKF_MALLOC (pContext, "lkf_setErrorFormat", sizeof(LKF_CONTEXT_ERRORFORMAT));
            if (!pErrorFormat) return LKF_OUTOFMEMORY_ERROR;
            pErrorFormat->fields = (unsigned int *) LKF_CALLOC (pContext, "lkf_setErrorFormat", count, sizeof (unsigned int));
            if (!pErrorFormat->fields) {
                LKF_FREE(pContext, "lkf_setErrorFormat", pErrorFormat);
                return LKF_OUTOFMEMORY_ERROR;
            }
            pErrorFormat->fieldcount = count;
            memcpy (pErrorFormat->fields, fields, sizeof (unsigned int) * count);
            pContext->pErrorFormats[i] = pErrorFormat;
        }
    }
    return 0;
}

int lkf_ErrorMatchesFilter (const LKF_CONTEXT *pContext, unsigned int nFilter, const LKF_SATZART_ERRORDEF *pErrorDef)
{
	unsigned int errorfiltermask = 1 << pErrorDef->nFacility;
	unsigned int nSev = lkf_getSeverity (pContext, pErrorDef);
    
	if (nSev & 1) errorfiltermask <<= 20;
	else if (nSev&3) errorfiltermask <<= 8;

	return (int) (nFilter & errorfiltermask);
}

static int sort_filtered_errors (const void *p1, const void *p2)
{
	const LKF_SATZART_ERROR **ppLeft, **ppRight;
	int nDiff;

	ppLeft = (const LKF_SATZART_ERROR **) p1;
	ppRight = (const LKF_SATZART_ERROR **) p2;

	if ((*ppLeft)->pAufenthalt)
	{
		if ((*ppRight)->pAufenthalt)
		{
			nDiff = strncmp ((*ppLeft)->pAufenthalt->PATID, (*ppRight)->pAufenthalt->PATID, 10);
			if (nDiff) return nDiff;
		}
		else
			return 1;
	}
	else if ((*ppRight)->pAufenthalt)
		return -1;

	nDiff = memcmp ((*ppLeft)->sErrorCode, (*ppRight)->sErrorCode, 4);
	if (nDiff) return nDiff;

	return (int)((*ppLeft)->nErrorLfdNr) - (int)((*ppRight)->nErrorLfdNr);
}

static int sort_filtered_errors_2017 (const void *p1, const void *p2)
{
    const LKF_SATZART_ERROR **ppLeft, **ppRight;
    int nDiff;
    
    ppLeft = (const LKF_SATZART_ERROR **) p1;
    ppRight = (const LKF_SATZART_ERROR **) p2;
    
    if ((*ppLeft)->pAufenthalt)
    {
        if ((*ppRight)->pAufenthalt)
        {
            nDiff = strncmp ((*ppLeft)->pAufenthalt->PATID, (*ppRight)->pAufenthalt->PATID, 12);
            if (nDiff) return nDiff;
        }
        else
            return 1;
    }
    else if ((*ppRight)->pAufenthalt)
        return -1;
    
    nDiff = memcmp ((*ppLeft)->sErrorCode, (*ppRight)->sErrorCode, 4);
    if (nDiff) return nDiff;
    
    return (int)((*ppLeft)->nErrorLfdNr) - (int)((*ppRight)->nErrorLfdNr);
}

_SCORING_EXPORT unsigned int lkf_setErrorCountsFilter (LKF_CONTEXT *pContext, unsigned int Filter) {
    unsigned int i, errorcount;
    LKF_SATZART_ERRORINFO *pErrors;
    
    errorcount = 0;
    
    if (pContext->pFilterErrorInfo) lkf_free_errorinfo (pContext->pFilterErrorInfo);

    
    if (pContext->pFullErrorCounters) {

        pContext->pFilterErrorInfo = (LKF_SATZART_ERRORINFO_LIST *) LKF_MALLOC (pContext, "lkf_setErrorCountsFilter", sizeof (LKF_SATZART_ERRORINFO_LIST));
        if (!pContext->pFilterErrorInfo) {
            return LKF_OUTOFMEMORY_ERROR;
        }
        pContext->pFilterErrorInfo->nAlloc = pContext->pFullErrorCounters->nCount;
        pContext->pFilterErrorInfo->nCount = 0;
        pErrors = (LKF_SATZART_ERRORINFO *) LKF_CALLOC (pContext, "lkf_setErrorCountsFilter", pContext->pFullErrorCounters->nCount, sizeof (LKF_SATZART_ERRORINFO));
        if (!pErrors) {
            LKF_FREE(pContext, "lkf_setErrorCountsFilter", pContext->pFilterErrorInfo);
            pContext->pFilterErrorInfo = 0;
            return LKF_OUTOFMEMORY_ERROR;
        }
        
        pContext->pFilterErrorInfo->pErrors = pErrors;
        pContext->pFilterErrorInfo->nListOptions = 0;
        pContext->pFilterErrorInfo->pContext = pContext;

        
        for (i = 0; i < pContext->pFullErrorCounters->nCount; i++) {
            LKF_SATZART_ERRORINFO *pError = pContext->pFullErrorCounters->pErrors + i;
            if (lkf_ErrorMatchesFilter (pContext, Filter, pError->pError)) {
                memcpy (pErrors + errorcount++, pError, sizeof(LKF_SATZART_ERRORINFO));
            }
        }
        pContext->pFilterErrorInfo->nCount = errorcount;
        lkf_errorinfo_sort (pContext->pFilterErrorInfo);
    }
    else
    {
        pContext->ppFilteredErrors = 0;
        pContext->nFilteredErrors = 0;
        pContext->pFilterErrorInfo = 0;
    }
    return errorcount;
    
}

_SCORING_EXPORT unsigned int lkf_setErrorFilter (LKF_CONTEXT *pContext, unsigned int Filter)
{
	unsigned int i, errorcount;
	const LKF_SATZART_ERROR **ppErrors;
	ERRORDEF_CACHE *pErrorDefCache;
	LKF_SATZART_ERRORINFO *pErrorInfo;

	errorcount = 0;

	if (pContext->ppFilteredErrors) LKF_FREE (pContext, "lkf_setErrorFilter", pContext->ppFilteredErrors);
	if (pContext->pFilterErrorInfo) lkf_free_errorinfo (pContext->pFilterErrorInfo);
    pContext->ppFilteredErrors = 0;
    pContext->pFilterErrorInfo = 0;
    
	if (pContext->pSatzartErrors && pContext->pSatzartErrors->nCount) {
		ppErrors = (const LKF_SATZART_ERROR **) LKF_CALLOC (pContext, "lkf_setErrorFilter", pContext->pSatzartErrors->nCount, sizeof (const LKF_SATZART_ERROR *));
        if (!ppErrors) {
            return LKF_OUTOFMEMORY_UINTERROR;
        }
        
		for (i = 0; i < pContext->pSatzartErrors->nCount; i++)
		{
            
            if (pContext->pSatzartErrors->pErrors[i].mainErrorIndex == -99) {
                continue;
            }
            
			if (lkf_ErrorMatchesFilter (pContext, Filter, (pContext->pSatzartErrors->pErrors + i)->pErrorDef))
				ppErrors[errorcount++] = pContext->pSatzartErrors->pErrors + i;
		}

		
		pContext->ppFilteredErrors = (LKF_SATZART_ERROR **) LKF_CALLOC (pContext, "lkf_setErrorFilter", sizeof (LKF_SATZART_ERROR *), errorcount);
        if (!pContext->ppFilteredErrors) {
            LKF_FREE (pContext, "lkf_setErrorFilter", ppErrors);
            return LKF_OUTOFMEMORY_UINTERROR;
        }
        
        pContext->nFilteredErrors = errorcount;
        memcpy ((void *) pContext->ppFilteredErrors, ppErrors, sizeof (const LKF_SATZART_ERROR **) * errorcount);
        LKF_FREE (pContext, "lkf_setErrorFilter", ppErrors);

		pErrorDefCache = lkf_errordefcache_create (pContext);
        if (!pErrorDefCache) {
            lkf_set_outOfMemory(pContext, "lkf_setErrorFilter", 0);
            return LKF_OUTOFMEMORY_UINTERROR;
        }
		pContext->pFilterErrorInfo = lkf_alloc_errorinfo (pContext, LKF_ERRORFILTER_ALL);
        if (!pContext->pFilterErrorInfo) {
            return LKF_OUTOFMEMORY_UINTERROR;
        }
		for (i = 0; i < errorcount; i++)
		{
			pErrorInfo = lkf_errorinfo_add (pContext->pFilterErrorInfo, pErrorDefCache, pContext->ppFilteredErrors[i]->pErrorDef, 1, 1);
			if (pErrorInfo) memcpy (pContext->ppFilteredErrors[i]->sErrorCode, pErrorInfo->sErrorCode, 4);
		}

		lkf_errorinfo_sort (pContext->pFilterErrorInfo);
        if (pContext->modelljahr >= 2017)
            qsort (pContext->ppFilteredErrors, errorcount, sizeof (const LKF_SATZART_ERROR *), sort_filtered_errors_2017);
        else
            qsort (pContext->ppFilteredErrors, errorcount, sizeof (const LKF_SATZART_ERROR *), sort_filtered_errors);

		lkf_errordefcache_free (pErrorDefCache);
	}
	else 
	{
		pContext->ppFilteredErrors = 0;
		pContext->nFilteredErrors = 0;
		pContext->pFilterErrorInfo = 0;
	}
	return errorcount;
}


static const LKF_CONTEXT_ERRORFORMAT *lkf_getErrorFormat (const LKF_CONTEXT *pContext, unsigned int facility)
{
	static unsigned int DefaultErrorNumbers[] = {CHECKFIELD_SATZART, CHECKFIELD_AUFNR, CHECKFIELD_IDENT, 
												 CHECKFIELD_CODE, CHECKFIELD_FELD_LANG, CHECKFIELD_FELDID,
												 CHECKFIELD_FELDNAME, CHECKFIELD_TEXT};
	static unsigned int DefaultErrorNumbersBM[] = {CHECKFIELD_SATZART, CHECKFIELD_AUFID64, CHECKFIELD_IDENT,
        CHECKFIELD_CODE, CHECKFIELD_FELD_LANG, CHECKFIELD_FELDID,
        CHECKFIELD_FELDNAME, CHECKFIELD_TEXT}; /* V19.0 */
	static LKF_CONTEXT_ERRORFORMAT DefaultErrorFormat = {8, DefaultErrorNumbers};
	static LKF_CONTEXT_ERRORFORMAT DefaultErrorFormatBM = {8, DefaultErrorNumbersBM}; /* V19.0 */

	if (facility < LKF_FAC_ALLOC && facility > 0 && pContext->pErrorFormats[facility])
		return pContext->pErrorFormats[facility];
	else if (pContext->pErrorFormats[0])
		return pContext->pErrorFormats[0];
	else if (pContext->isBM)
        return &DefaultErrorFormatBM;
    else
		return &DefaultErrorFormat;
}

static const char *lkf_getGetKostenstelle (const LKF_CONTEXT *pContext, const char *sAbtFC, char *sKostenstelle)
{

	const LKF_CONTEXT_ABTEILUNG *pAbt = lkf_context_find_abteilung (pContext, sAbtFC);

	if (!pAbt)
		strcpy (sKostenstelle, "????????");
	else
		strcpy (sKostenstelle, pAbt->sKst8);
	return sKostenstelle;
}

/*******************************************************************************************************
** lkf_getErrorFieldValue:                                                                            **
**      Liefert einen Error-Feldwert zurueck                                                          **
*******************************************************************************************************/

const char *lkf_getErrorFieldValue (const LKF_CONTEXT *pContext, const LKF_SATZART_ERROR *pError, unsigned int checkfield, unsigned int buflen, char *buf, unsigned int *pFieldLen)
{
	unsigned int nSev;
	unsigned int fieldlen;
	unsigned int i;
	int nAbtIndex;
	char field[80];
	const SATZART_FELD *pFeld;
	const char *pBuf;
    const char *fucoAufNr;
    char satzart[6];
    
	switch (checkfield)
	{
		case CHECKFIELD_KANR:
			fieldlen = 10;
			if (pFieldLen) *pFieldLen = fieldlen;
            
			if (buflen > 10)
			{
                if (pError->KANR[0]) {
                    sprintf (buf, "%-6.6s    ", pError->KANR);
                }
                else if (pContext->standortInfo && pError->pAufenthalt && pError->nAbtIndex >= 0 && pError->pAufenthalt->abt_anz > (unsigned int) pError->nAbtIndex)
                {
                    LKF_CONTEXT_ABTEILUNG *pAbt = lkf_context_find_abteilung (pContext, pError->pAufenthalt->abt[pError->nAbtIndex].ABTFC);
                    if (pAbt)
                        sprintf (buf, "%-6.6s    ", pAbt->sKANR6);
                    else
                        sprintf (buf, "%4.4s      ", pContext->KANR);
                }
                else {
                    sprintf (buf, "%4.4s      ", pContext->KANR);
                }
                return buf;
			}
			break;

		case CHECKFIELD_KST:
		case CHECKFIELD_ENTKST:
		case CHECKFIELD_KST_ENTKST:
			fieldlen = 8; /* V2021.1 */
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pAufenthalt) 
			{
				if (pError->pAufenthalt->abt_anz == 0)
					nAbtIndex = -1;
				else if (pError->nAbtIndex >= 0 && checkfield != CHECKFIELD_ENTKST)
					nAbtIndex = pError->nAbtIndex;
				else if (checkfield == CHECKFIELD_KST || checkfield == CHECKFIELD_KST_ENTKST)
					nAbtIndex = -1;
				else
					nAbtIndex = (int) (pError->pAufenthalt->abt_anz - 1);
				if (nAbtIndex >= 0)
					return lkf_getGetKostenstelle (pContext, pError->pAufenthalt->abt[nAbtIndex].ABTFC, buf);

			}
			else if (pError->pSatzartInfo)
			{
				pFeld = pError->pSatzartInfo->ppRef[GEN_ABTFC];
				if (buflen > fieldlen && pFeld)
				{
					char sAbtFC[10];
					Satzart_GetValueString (pError->pLine, (unsigned int) strlen (pError->pLine), pFeld, sAbtFC, 10);
					return lkf_getGetKostenstelle (pContext, sAbtFC, buf);
				}
			}
			break;

        case CHECKFIELD_CHILD_IDENT:
            fieldlen = 15;
            if (pFieldLen) *pFieldLen = fieldlen;
            fucoAufNr = 0;
            if (pError->pAufenthalt) {
                lkf_getErrorMBDSSatzart(pError->pAufenthalt, pError->pErrorDef->nAddInfo, 4, satzart);
                switch (satzart[2]) {
                    case '2':
                        if (pError->nAddInfo < pError->pAufenthalt->abt_anz)
                            fucoAufNr = pError->pAufenthalt->abt[pError->nAddInfo].ABT_IDENT;
                        break;
                    case '3':
                        if (pError->nAddInfo < pError->pAufenthalt->diag_anz) {
                            fucoAufNr = pError->pAufenthalt->diag[pError->nAddInfo].DIAG_IDENT;
                        }
                        break;
                    case '4':
                        fucoAufNr = pError->pAufenthalt->mel[pError->nAddInfo].MEL_IDENT;
                        break;
                    default:
                        break;
                }
            }
            if (buflen >= 15 && fucoAufNr) {
                strncpy(buf, fucoAufNr, 15);
                if (buflen > 15) buf[15] = 0;
                return buf;
            }
            break;

            
        case CHECKFIELD_FUCOAUFNR:
            fieldlen = 12;
            if (pFieldLen) *pFieldLen = fieldlen;
			fucoAufNr = 0;
			if (pError->pAufenthalt) {
				lkf_getErrorMBDSSatzart(pError->pAufenthalt, pError->pErrorDef->nAddInfo, 4, satzart);
				switch (satzart[2]) {
				case '2':
					if (pError->nAddInfo < pError->pAufenthalt->abt_anz)
						fucoAufNr = pError->pAufenthalt->abt[pError->nAddInfo].FUCOAUFNR;
					break;
				case '3':
                    if (pError->nAddInfo < pError->pAufenthalt->diag_anz)
                        fucoAufNr = pError->pAufenthalt->diag[pError->nAddInfo].FUCOAUFNR;
                    break;
				case '4':
					fucoAufNr = pError->pAufenthalt->mel[pError->nAddInfo].FUCOAUFNR;
					break;
				default:
					break;
				}
			}
            
            if (buflen >= 12 && fucoAufNr) {
                strncpy(buf, fucoAufNr, 12);
                if (buflen > 12) buf[12] = 0;
                return buf;
            }
            break;
            
        case CHECKFIELD_AUFENTHALTINDEX:
            fieldlen = 7;
            if (buflen >= 8) {
                if (pError->pAufenthalt) {
                    sprintf (buf, "%7d", pError->pAufenthalt->indexInContext);
                }
                else {
                    sprintf(buf, "-1     ");
                }
                return buf;
            }
            break;
		case CHECKFIELD_ABTFCENTINDEX: 
		case CHECKFIELD_ABTFCENT:
		case CHECKFIELD_ABTFCINDEX:
		case CHECKFIELD_ABTFC:
		case CHECKFIELD_ENTABT:
		case CHECKFIELD_ENTABTINDEX:
        case CHECKFIELD_AUFABT:

			if (checkfield == CHECKFIELD_ENTABTINDEX || checkfield == CHECKFIELD_ABTFCENTINDEX || checkfield == CHECKFIELD_ABTFCINDEX)
                fieldlen = pContext->modelljahr >= 2017 ? 12 : 11;
			else
				fieldlen = 8;
			
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pAufenthalt) 
			{
				if (pError->pAufenthalt->abt_anz == 0)
					nAbtIndex = -1;
                else if (checkfield == CHECKFIELD_AUFABT)
                { /* V2025.1 */
                    nAbtIndex = 0;
                }
				else if (pError->nAbtIndex >= 0 && checkfield != CHECKFIELD_ENTABT && checkfield != CHECKFIELD_ENTABTINDEX)
					nAbtIndex = pError->nAbtIndex;
				else if (checkfield == CHECKFIELD_ABTFC || checkfield == CHECKFIELD_ABTFCINDEX)
					nAbtIndex = -1;
				else
					nAbtIndex = (int) (pError->pAufenthalt->abt_anz - 1);

				if (buflen > fieldlen && nAbtIndex >= 0)
				{
                    if (fieldlen == 12) {
                        char abtposbuf[6];
                        sprintf (buf, "%3.3s:%8.8s", lkf_format_abtpos (pError->pAufenthalt->abt + nAbtIndex, abtposbuf), pError->pAufenthalt->abt[nAbtIndex].ABTFC);
                    }
					if (fieldlen == 11)
						sprintf (buf, "%2.2s:%8.8s", pError->pAufenthalt->abt[nAbtIndex].ABTPOS, pError->pAufenthalt->abt[nAbtIndex].ABTFC);
					else
						sprintf (buf, "%8.8s", pError->pAufenthalt->abt[nAbtIndex].ABTFC); 
					return buf;
				}
			}
			else if (pError->pSatzartInfo)
			{
				pFeld = pError->pSatzartInfo->ppRef[GEN_ABTFC];
				if (buflen > fieldlen && pFeld)
				{
                    if (pError->pLine != 0) {
                        if (pContext->modelljahr < 2017) {
                            Satzart_GetValueString (pError->pLine, (unsigned int) strlen (pError->pLine), pFeld, buf + 3, buflen - 3);
                            if (fieldlen == 11)
                            {
                                memset (buf, ' ', 3);
                                Satzart_GetValueString (pError->pLine, (unsigned int) strlen (pError->pLine), pFeld, buf + 3, buflen - 3);
                            }
                            else
                                Satzart_GetValueString (pError->pLine, (unsigned int) strlen (pError->pLine), pFeld, buf, buflen);
                        }
                        else
                            break;
                    }
                    else if (pError->pExpLine)
                    {
                        Satzart_GetValueStringExp (pError->pExpLine, pFeld, buf + 3, buflen - 3);
                        if (fieldlen == 11)
                        {
                            memset (buf, ' ', 3);
                            Satzart_GetValueStringExp (pError->pExpLine, pFeld, buf + 3, buflen - 3);
                        }
                        else
                            Satzart_GetValueStringExp (pError->pExpLine, pFeld, buf, buflen);
                    }
                    
                    
					return buf;
				}
			}
			break;

		case CHECKFIELD_AUFNR:
            if (pContext && pContext->modelljahr >= 2017) {
                fieldlen = 12;
                if (pFieldLen) *pFieldLen = fieldlen;
                if (pError->pAufenthalt)
                {
                    if (buflen > 12) {
                        sprintf (buf, "%12.12s", pError->pAufenthalt->PATID);
                        return buf;
                    }
                }
            }
            else {
                fieldlen = 10;
                if (pFieldLen) *pFieldLen = fieldlen;
                if (pError->pAufenthalt)
                {
                    if (buflen > 10) {
                        sprintf (buf, "%10.10s", pError->pAufenthalt->PATID);
                        return buf;
                    }
                }
            }
			break;
            
		case CHECKFIELD_AUFID64:
			fieldlen = 64;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pAufenthalt)
			{
				if (buflen > 64) {
					sprintf (buf, "%64.64s", pError->pAufenthalt->UCASE_PATID);
					return buf;
				}
			}
			break;

            
		case CHECKFIELD_AUFDAT:
			fieldlen = 10;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pAufenthalt) 
			{
				if (buflen > 10) {
					FormatDate8 (pError->pAufenthalt->AUFDAT, buf);
					return buf;
				}
			}
			break;

		case CHECKFIELD_GEBDAT:
			fieldlen = 10;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pAufenthalt) 
			{
				if (buflen > 10) {
					FormatDate8 (pError->pAufenthalt->GEBDAT, buf);
					return buf;
				}
			}
			else 
			{
				fieldlen = 10;
			}
			break;

        case CHECKFIELD_ALTER:
        case CHECKFIELD_ALTER2:
			fieldlen = 6;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pAufenthalt)
			{
				if (buflen > 6) {
					sprintf (buf, "%6.6s", pError->pAufenthalt->ALTERSGRUPPE);
					return buf;
				}
			}
			else
			{
				fieldlen = 10;
			}
			break;

        
        case CHECKFIELD_GESCHL:
			fieldlen = 6;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pAufenthalt) 
			{
				if (buflen > 6) {
					sprintf (buf, "%c     ", pError->pAufenthalt->GESCHL);
					return buf;
				}
			}
			break;
		case CHECKFIELD_ENTDAT:
			fieldlen = 10;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pAufenthalt) 
			{
				if (buflen > 10) {
					FormatDate8 (pError->pAufenthalt->ENTDAT, buf);
					return buf;
				}
			}
			break;

		case CHECKFIELD_BERICHTSTYP:
			fieldlen = 11;
			if (pFieldLen) *pFieldLen = fieldlen;
			strcpy (buf, pError->sTyp);
			return buf;
			break;
		case CHECKFIELD_SATZART:
			fieldlen = 7;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pSatzartInfo) {
				if (buflen > 3) {
					sprintf (buf, "%-3.3s    ", pError->pSatzartInfo->pSatzart->sPrefix);
					return buf;
				}
			}
			else if (pError->pErrorDef->nFacility == LKF_FAC_MBDS && pError->pAufenthalt) {
				lkf_getErrorMBDSSatzart (pError->pAufenthalt, pError->pErrorDef->nAddInfo, buflen, buf);
				return buf;
			}
			else if (pError->pLine && buflen > 3) 
			{
				sprintf (buf, "%-3.3s", pError->pLine);
				return buf;
			}
			break;

		case CHECKFIELD_CODE:
			fieldlen = 9;
			if (pFieldLen) *pFieldLen = fieldlen;

			lkf_getErrorIdent (pContext, pError->pErrorDef, 10, field);
            if (pError->mainErrorIndex >= 0) {
                sprintf (buf, "* %4.4s   ", field);
            }
            else {
                sprintf (buf, "%4.4s     ", field);
            }
			return buf;

		case CHECKFIELD_IDENT:
			fieldlen = 30;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pSatzartInfo && (pError->pLine || (pContext->modelljahr > 2024 &&  pError->pExpLine)))
			{
				char ident[512];
				const SATZART *pSatzart = pError->pSatzartInfo->pSatzart;
				if (pSatzart->nErrorIdentFields) {
					i = 0;
					ident[0] = 0;
                    
                    if (pError->pExpLine) {
                        while (pSatzart->nErrorIdentFields[i] >= 0) {
                            Satzart_GetValueStringExp(pError->pExpLine, pSatzart->Felder + pSatzart->nErrorIdentFields[i], field, 80);
                            if (i > 0) strcat (ident, "/");
                            strcat (ident, field);
                            ++i;
                        }
                    }
                    else {
                        
                        while (pSatzart->nErrorIdentFields[i] >= 0) {
                            
                            unsigned int buflen = (unsigned int) strlen (pError->pLine);
                            
                            if (pContext->modelljahr >= 2017) {
                                if (buflen == LKF_LEN_FOR_EXPANDEDLINE) {
                                    Satzart_GetValueStringExp((const LKF_EXPANDED_LINE *) pError->pLine, pSatzart->Felder + pSatzart->nErrorIdentFields[i], field, 80);
                                }
                                else {
                                    const SATZART_FELD *pFeld = pSatzart->Felder + pSatzart->nErrorIdentFields[i];
                                    const char *pos = pError->pLine;
                                    int pipeCount = pFeld->nFieldNum + 1;
                                    while (pipeCount > 0 && (pos = strchr(pos, '|'))) {
                                        --pipeCount;
                                        ++pos;
                                    }
                                    if (pos) {
                                        const char *nextPos = strchr(pos, '|');
                                        int fieldLen = nextPos != 0 ? (int) (nextPos - pos) : (int) strlen (pos);
                                        if (fieldLen > 16) fieldLen = 16;
                                        memcpy (field, pos, fieldLen);
                                        field[fieldLen] = 0;
                                    }
                                    else {
                                        field[0] = 0;
                                    }
                                }
                            }
                            else {
                                Satzart_GetValueString (pError->pLine, buflen, pSatzart->Felder + pSatzart->nErrorIdentFields[i], field, 80);
                            }
                            
                            if (i > 0) strcat (ident, "/");
                            strcat (ident, field);
                            ++i;
                        }
                    }
				}
				else ident[0] = 0;
				strncpy (buf, ident, buflen);
				buf[buflen-1] = 0;
				return buf;
			}
			else if (pError->pErrorDef->nFacility == LKF_FAC_MBDS && pError->pAufenthalt) 
				return lkf_getErrorMBDSIdent (pError->pAufenthalt, pError->pErrorDef->nAddInfo, pError->nAddInfo, buflen, buf);
			else if (pError->pLine)
			{
				sprintf (buf, "%-30.30s", pError->pLine);
				return buf;
			}
			else 
			{
				buf[0] = 0;
				return buf;
			}
		case CHECKFIELD_MASSNAHME:
			fieldlen = 9;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (buflen > 9) {
				nSev = lkf_getSeverity (pContext, pError->pErrorDef);
                if (nSev == LKF_SEV_WARNING_PRUEF)
                    strcpy (buf, pContext->modelljahr >= 2017 ? "Pruefung " : "Prüfung  ");
				else if (nSev == LKF_SEV_WARNING_KORR) strcpy (buf, "Korrektur");
				else strcpy (buf, "         ");
			}
			return buf;
		case CHECKFIELD_ACCEPTABLE:
			fieldlen = 4;
			if (*pFieldLen) *pFieldLen = fieldlen;
			if (buflen > fieldlen) {
				if (pError->pErrorDef) {
					if (pError->pErrorDef->nSeverity & LKF_SEV_ACCEPTABLE)
						strcpy(buf, "JA  ");
					else
						strcpy(buf, "NEIN");
				}
				else {
					strcpy(buf, "?   ");
				}
			}
			return buf;
		case CHECKFIELD_TEXT150BYTE:
        case CHECKFIELD_TEXT150CHAR:
		case CHECKFIELD_TEXT:
			
			pBuf = lkf_context_formatted_text (pContext, pError->pErrorDef->sText, buf);
			if (pBuf != buf) strcpy(buf, pBuf);
            
            if (checkfield == CHECKFIELD_TEXT) {
                fieldlen = 0;
            }
            else if (checkfield == CHECKFIELD_TEXT150CHAR && pContext->utf8_mode) {
                fieldlen = 150 + lkf_numberOf2ByteCharaters(pContext, pError->pErrorDef->sText);
            }
            else {
                fieldlen = 150;
            }
            
            if (pFieldLen) *pFieldLen = fieldlen;
            return buf;
		case CHECKFIELD_FELDID:
			fieldlen = 10;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (buflen > 10 && pError->pSatzartInfo && pError->pFeld)  
			{
				sprintf (buf, "%02d/%03d_%03d", pError->pFeld->nFieldNum, pError->pFeld->nPos, pError->pFeld->nLen);
				return buf;
			}
			else if (pError->pErrorDef->nFacility == LKF_FAC_MBDS) {
				strncpy (buf, lkf_getErrorMBDSFieldId (pContext, pError->pErrorDef->nAddInfo), buflen);
				buf[buflen-1] = 0;
			}
			break;
		case CHECKFIELD_FELDNAME:
			fieldlen = 20;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->pFeld) {
				strncpy (buf, pError->pFeld->sFeldName, buflen);
				buf[buflen-1] = 0;
				return buf;
			}
			else if (pError->pErrorDef->nFacility == LKF_FAC_MBDS) {
				strncpy (buf, lkf_getErrorMBDSFieldId (pContext, pError->pErrorDef->nAddInfo), buflen);
				buf[buflen-1] = 0;
			}
			break;
		case CHECKFIELD_FELD:
		case CHECKFIELD_FELD_LANG:
			fieldlen = (checkfield == CHECKFIELD_FELD_LANG) ? 22 : 11;
			if (pFieldLen) *pFieldLen = fieldlen;
			if (pError->sErrorFeld[0])
			{
				strncpy (buf, pError->sErrorFeld, buflen);
				buf[buflen-1] = 0;
				return buf;
			}
			else if (pError->pLine && pError->pFeld) {
				unsigned int linelen = (unsigned int) strlen(pError->pLine);
				if (!Satzart_IsEmpty (pError->pLine, linelen, pError->pFeld)) {

					if (pContext->modelljahr >= 2017) {
                        
                        if (pError->pSatzartInfo)
                        { /* V21.2 */
                            Satzart_GetValueString2017 (pError->pLine, linelen, pError->pFeld, pError->pSatzartInfo->feldIndex[pError->pFeld->nFieldNum], buf, buflen);
                        }
                        else {
                            *buf = 0;
                        }
					}
					else {
						Satzart_GetValueString (pError->pLine, linelen, pError->pFeld, buf, buflen);
					}

					buf[buflen-1] = 0;

					if (pError->pFeld->nType == TYP_DAT)
					{
						memcpy (field, buf, 8);
						field[8] = 0;
						FormatDate8 (field, buf);
					}

					return buf;
				}
			}
            else if (pError->pExpLine && pError->pFeld) {
                if (!Satzart_IsEmptyExp (pError->pExpLine, pError->pFeld)) {
                    Satzart_GetValueStringExp (pError->pExpLine, pError->pFeld, buf, buflen);
                    buf[buflen-1] = 0;
                    
                    if (pError->pFeld->nType == TYP_DAT)
                    {
                        memcpy (field, buf, 8);
                        field[8] = 0;
                        FormatDate8 (field, buf);
                    }
                    return buf;
                }
            }
			else if (pError->pErrorDef->nFacility == LKF_FAC_MBDS && pError->pAufenthalt)
			{
				lkf_getErrorMBDSFieldEx (pError->pAufenthalt, pError->pErrorDef->nAddInfo, pError->nAddInfo, buf, buflen, pError->nAbtIndex);
				buf[buflen-1] = 0;
				return buf;
			}
			fieldlen = 11;
			break;
		default:
            if (checkfield > 10000 && pError->pErrorDef->nFacility == LKF_FAC_MBDS && pError->pAufenthalt)
            { /* V2023.1: export MBDS error fields */
                lkf_getErrorMBDSFieldEx (pError->pAufenthalt, checkfield - 10000, pError->nAddInfo, buf, buflen, pError->nAbtIndex);
                buf[buflen-1] = 0;
                return buf;
            }
			if (pFieldLen) *pFieldLen = 0;
			if (buflen > 0) buf[0] = 0;		
			return buf;
	}

	memset (buf, ' ', fieldlen);
	buf[fieldlen] = 0;
	return buf;
}

/*******************************************************************************************************
** lkf_getErrorFieldHeadline:                                                                         **
**      Liefert die Überschrift zu einem Error-Feldwert zurück.                                       **
*******************************************************************************************************/

const char *lkf_getErrorFieldHeadline (const LKF_CONTEXT *pContext, unsigned int checkfield)
{

	switch (checkfield) 
	{
        case CHECKFIELD_AUFENTHALTINDEX:
            return "INDEX# ";
		case CHECKFIELD_ENTABTINDEX: return "ENTABT     ";
        case CHECKFIELD_AUFABT:        return "AUFABT  ";    
        case CHECKFIELD_ENTABT:		return "ENTABT  ";
		case CHECKFIELD_KANR:
			if (pContext->isKTR)
				return "TNR       ";
			else		
				return "KANR      ";	
		case CHECKFIELD_AUFNR:
            
            if (pContext && pContext->modelljahr >= 2017)
                return "AUFZAHL     ";
            else
                return "AUFZAHL   ";
        case CHECKFIELD_AUFID64:    return "AUFID                                                           ";
		case CHECKFIELD_AUFDAT:		return "AUFDAT    ";
		case CHECKFIELD_GEBDAT:		return "GEBDAT    ";
        case CHECKFIELD_ALTER2:
        case CHECKFIELD_ALTER:      return "ALTER ";
		case CHECKFIELD_GESCHL:		return "GESCHL";
		case CHECKFIELD_ENTDAT:		return "ENTDAT    ";
        case CHECKFIELD_FUCOAUFNR:  return "FUCO-AUFNR  ";
        case CHECKFIELD_CHILD_IDENT: return "X02/03/04-IDENT";
		case CHECKFIELD_BERICHTSTYP: return "BERICHTSTYP";
		case CHECKFIELD_SATZART:	return "SATZ   ";
		case CHECKFIELD_CODE:		return "CODE     ";
		case CHECKFIELD_IDENT:		return "SATZ-IDENTIFIKATION           ";
		case CHECKFIELD_MASSNAHME:	return "MASSNAHME";
		case CHECKFIELD_ACCEPTABLE: return "AKZ.";
		case CHECKFIELD_TEXT:		return "KOMMENTAR";
        case CHECKFIELD_TEXT150BYTE:
        case CHECKFIELD_TEXT150CHAR:
            return "KOMMENTAR                                                                                                                                             ";
		case CHECKFIELD_FELD:		return "WERT       ";
		case CHECKFIELD_FELD_LANG:  return "WERT                  ";
		case CHECKFIELD_FELDID:		return "FELD-ID   ";
		case CHECKFIELD_FELDNAME:   return "FELDNAME            ";
		case CHECKFIELD_KST:
		case CHECKFIELD_ENTKST:
		case CHECKFIELD_KST_ENTKST:
									return "KST     "; /* V2021.1 - zwei Blanks*/
		case CHECKFIELD_ABTFCENTINDEX:
		case CHECKFIELD_ABTFCINDEX: return "ABTFC      ";
		case CHECKFIELD_ABTFCENT:
		case CHECKFIELD_ABTFC:		return "ABTFC   ";

		default:					return "";
	}
}

_SCORING_EXPORT unsigned int lkf_getSatzartErrorHeadline (const LKF_CONTEXT *pContext, unsigned int nFacility, unsigned int nBufLen, char *sBuf)
{
	unsigned int i, l, offset;
	const char *fieldheadline;
	const LKF_CONTEXT_ERRORFORMAT *pErrorFormat = lkf_getErrorFormat (pContext, nFacility);

	offset = 0;

	for (i = 0; i < pErrorFormat->fieldcount; i++) {
		fieldheadline = lkf_getErrorFieldHeadline (pContext, pErrorFormat->fields[i]);
		l = (unsigned int) strlen (fieldheadline);
		if (i == 0) {
			if (l < nBufLen) strcpy (sBuf, fieldheadline);
			offset += l;
		}
		else {
			if (nBufLen - offset > l + 3) {
				sprintf (sBuf + offset, " ; %s", fieldheadline);
			}
			offset += l + 3;
		}
	}
	
	return offset;
}

_SCORING_EXPORT unsigned int lkf_getSatzartErrorFieldHeadline (const LKF_CONTEXT *pContext, unsigned int nFieldNumber, char *sBuf, unsigned int nBufLen)
{
	unsigned int nLen;
	const char *pHeadline = lkf_getErrorFieldHeadline (pContext, nFieldNumber);
	if (!pHeadline) pHeadline = "";

	nLen = (unsigned int) strlen (pHeadline);
	strncpy (sBuf, pHeadline, nBufLen);
	if (nLen >= nBufLen) sBuf[nBufLen - 1] = 0;
	return nLen;
}

_SCORING_EXPORT unsigned int lkf_getSatzartErrorField (const LKF_CONTEXT *pContext, unsigned int nErrorIndex, unsigned int nFieldNumber, char *sBuf, unsigned int nBufLen)
{
	unsigned int nLen;
	char FieldBuffer[512];
	const LKF_SATZART_ERROR *pError;
	unsigned int nFieldLen;

	pError = 0;

	if (pContext->ppFilteredErrors) {
		if (pContext->nFilteredErrors > nErrorIndex) pError = pContext->ppFilteredErrors[nErrorIndex];
	}
	else {
		if (pContext->pSatzartErrors && pContext->pSatzartErrors->nCount > nErrorIndex)
			pError = pContext->pSatzartErrors->pErrors + nErrorIndex;
	}

	if (pError) 
	{
		lkf_getErrorFieldValue (pContext, pError, nFieldNumber, 512, FieldBuffer, &nFieldLen);
	}
	else 
	{
		FieldBuffer[0] = 0;
	}

	nLen = (unsigned int) strlen (FieldBuffer);
	strncpy (sBuf, FieldBuffer, nBufLen);
	if (nLen >= nBufLen) sBuf[nBufLen - 1] = 0;
	return nLen;
}

_SCORING_EXPORT LKF_CONTEXT_ERRORFORMAT *lkf_createErrorFormat (unsigned int fieldcount, const unsigned int *fields)
{ /* V2022.1 */
    LKF_CONTEXT_ERRORFORMAT *fmt = (LKF_CONTEXT_ERRORFORMAT *) LKF_MALLOC (0, "lkf_createErrorFormat", sizeof(LKF_CONTEXT_ERRORFORMAT));
    if (!fmt) return 0;
    fmt->fields = (unsigned int *) LKF_CALLOC (0, "lkf_createErrorFormat.fields", sizeof (unsigned int), fieldcount);
    if (!fmt->fields) {
        LKF_FREE(0, "lkf_createErrorFormat", fmt);
        return 0;
    }
    fmt->fieldcount = fieldcount;
    memcpy (fmt->fields, fields, sizeof (unsigned int) * fieldcount);
    return fmt;
}

_SCORING_EXPORT void lkf_freeErrorFormat (LKF_CONTEXT_ERRORFORMAT *errorFormat)
{ /* V2022.1 */
    if (errorFormat) {
        LKF_FREE(0, "lkf_freeErrorFormat", errorFormat->fields);
        LKF_FREE(0, "lkf_freeErrorFormat", errorFormat);
    }
}

_SCORING_EXPORT unsigned int lkf_getSatzartErrorFromFields (const LKF_CONTEXT *pContext, const LKF_SATZART_ERROR *pError, unsigned int fieldCount, const unsigned int *fields, unsigned int nBufLen, char *sBuf) {
    unsigned int i, offset, l;
    unsigned int fieldlen;
    char fieldbuf[512];
    offset = 0;
    for (i = 0; i < fieldCount; i++) {
        lkf_getErrorFieldValue (pContext, pError, fields[i], 512, fieldbuf, &fieldlen);
        l = (unsigned int) strlen (fieldbuf);
        if (!fieldlen || i + 1 == fieldCount) fieldlen = l;
        if (i == 0) {
            if (fieldlen < nBufLen) {
                strcpy (sBuf, fieldbuf);
                if (l < fieldlen) {
                    memset (sBuf + l, ' ', fieldlen - l);
                    sBuf[fieldlen] = 0;
                }
            }
            offset += fieldlen;
        }
        else {
            if (nBufLen - offset > fieldlen + 3) {
                sprintf (sBuf + offset, " ; %s", fieldbuf);
                if (l < fieldlen)
                {
                    memset (sBuf + offset + l + 3, ' ', fieldlen - l);
                    sBuf[offset + fieldlen + 3] = 0;
                }
            }
            offset += fieldlen + 3;
        }
    }

    return offset;
}

_SCORING_EXPORT unsigned int lkf_getSatzartErrorFromFormat (const LKF_CONTEXT *pContext, const LKF_SATZART_ERROR *pError, const LKF_CONTEXT_ERRORFORMAT *pErrorFormat, unsigned int nBufLen, char *sBuf) {
    return lkf_getSatzartErrorFromFields(pContext, pError, pErrorFormat->fieldcount, pErrorFormat->fields, nBufLen, sBuf);
}

_SCORING_EXPORT unsigned int lkf_getSatzartError (const LKF_CONTEXT *pContext, unsigned int nErrorIndex, unsigned int nBufLen, char *sBuf)
{
	const LKF_SATZART_ERROR *pError;
	const LKF_CONTEXT_ERRORFORMAT *pErrorFormat;

	if (pContext->ppFilteredErrors) {
		if (pContext->nFilteredErrors <= nErrorIndex) return 0;
		pError = pContext->ppFilteredErrors[nErrorIndex];
	}
	else {
		if (!pContext->pSatzartErrors || pContext->pSatzartErrors->nCount <= nErrorIndex) return 0;
		pError = pContext->pSatzartErrors->pErrors + nErrorIndex;
	}

	pErrorFormat = lkf_getErrorFormat (pContext, pError->pErrorDef->nFacility);
    return lkf_getSatzartErrorFromFormat (pContext, pError, pErrorFormat, nBufLen, sBuf);
}

_SCORING_EXPORT unsigned int lkf_getSatzartErrorFields (const LKF_CONTEXT *pContext, unsigned int nErrorIndex, unsigned int fieldCount, const unsigned int *fields, unsigned int nBufLen, char *sBuf)
{
    const LKF_SATZART_ERROR *pError;

    if (pContext->ppFilteredErrors) {
        if (pContext->nFilteredErrors <= nErrorIndex) return 0;
        pError = pContext->ppFilteredErrors[nErrorIndex];
    }
    else {
        if (!pContext->pSatzartErrors || pContext->pSatzartErrors->nCount <= nErrorIndex) return 0;
        pError = pContext->pSatzartErrors->pErrors + nErrorIndex;
    }

    return lkf_getSatzartErrorFromFields (pContext, pError, fieldCount, fields, nBufLen, sBuf);
}



/*************************************************************************************
** lkf_errorlist_code2id:                                                           **
**        Liefert die Error-Id zum 4stelligen Error-Code einer Error-List.          **
*************************************************************************************/

static int lkf_search_errorinfo (const void *key, const void *compare)
{
	return memcmp (key, ((const LKF_SATZART_ERRORINFO *)compare)->sErrorCode, 4);
}

static int lkf_errorlist_code2id (const LKF_SATZART_ERRORINFO_LIST *pList, const char *sCode)
{
	const LKF_SATZART_ERRORINFO *pErrorInfo;
	pErrorInfo = (const LKF_SATZART_ERRORINFO *) bsearch (sCode, pList->pErrors, pList->nCount, sizeof (LKF_SATZART_ERRORINFO), lkf_search_errorinfo);
	if (pErrorInfo) return (int) (pErrorInfo - pList->pErrors);
	else return -1;
}

/*************************************************************************************
** lkf_errorlist_getErrorField:                                                     **
**        Liefert zu einem Error in der Errorlist das zugehörige Feld.              **
*************************************************************************************/

static unsigned int lkf_errorlist_getErrorField (const LKF_SATZART_ERRORINFO *pErrorInfo, unsigned int nField, char *sBuf, unsigned int nBufLen)
{
    const char *pErrorText;
	char sLocalBuf[240];
	unsigned int nLen;

	switch (nField)
	{
		case LKF_ERRORCODE_ID:
			sprintf (sLocalBuf, "%4.4s", pErrorInfo->sErrorCode);
			break;

		case LKF_ERRORCODE_TEXT:
            pErrorText = lkf_context_formatted_text (pErrorInfo->pContext, pErrorInfo->pError->sText, sLocalBuf);
			strncpy (sBuf, pErrorText, nBufLen);
			nLen = (unsigned int) strlen (pErrorText);
			if (nLen >= nBufLen) sBuf[nBufLen-1] = 0;
			return nLen;

		case LKF_ERRORCODE_COUNT:
			sprintf (sLocalBuf, "%5d", pErrorInfo->nOccurrences);
			break;

		case LKF_ERRORCODE_FOND_REL:
			sprintf (sLocalBuf, "%c", pErrorInfo->nFonds ? 'X' : ' ');
			break;

		case LKF_ERRROCODE_NFOND_REL:
			sprintf (sLocalBuf, "%c", pErrorInfo->nNichtFonds ? 'X' : ' ');
			break;

		case LKF_ERRORCODE_SEVERITY:
			sprintf (sLocalBuf, "%4d", lkf_getSeverity (pErrorInfo->pContext, pErrorInfo->pError));
			break;

		case LKF_ERRORCODE_FACILITY:
			sprintf (sLocalBuf, "%4d", pErrorInfo->pError->nFacility);
			break;

		case LKF_ERRORCODE_OLDCODE:
			sprintf (sLocalBuf, "%4d", pErrorInfo->pError->nCode);
			break;

		default:
			sLocalBuf[0] = 0;
	}
	nLen = (unsigned int) strlen (sLocalBuf);
	strncpy (sBuf, sLocalBuf, nBufLen);
	if (nLen >= nBufLen) sBuf[nBufLen-1] = 0; 
	return 0;
}

_SCORING_EXPORT const char *lkf_satzart_getValue (const LKF_CONTEXT *pContext, const LKF_SATZART_ERROR *pError, unsigned int nField, char *buf, unsigned int buflen)
{
    unsigned int fieldLen;
    const char *ret = lkf_getErrorFieldValue (pContext, pError, nField, buflen, buf, &fieldLen);
    if (ret) {
        if (ret != (const char *) buf) {

			if (fieldLen > 0) {
				if (buflen < fieldLen + 1)
					fieldLen = buflen - 1;
				strncpy(buf, ret, fieldLen);
				buf[fieldLen] = 0;
			}
			else {
				strncpy(buf, ret, buflen);
			}
        }
        else if (fieldLen > 0) {
            if (buflen < fieldLen + 1) {
                fieldLen = buflen - 1;
            }
            buf[fieldLen] = 0;
        }
    }
    return ret;
}

/*************************************************************************************
** lkf_getSatzartErrorSum_Count:                                                    **
**        Liefert die Anzahl verschiedener Error-Codes der letzten Filterung.       **
*************************************************************************************/

_SCORING_EXPORT unsigned int lkf_getSatzartErrorSum_Count (const LKF_CONTEXT *pContext)
{
	if (pContext->pFilterErrorInfo) return pContext->pFilterErrorInfo->nCount;
	else return 0;
}

/*************************************************************************************
** lkf_context_getAllErrorInfo_CodeToId:                                            **
**        Liefert die Error-Id zum 4stelligen Error-Code                            **
*************************************************************************************/

_SCORING_EXPORT int lkf_context_getAllErrorInfo_CodeToId (const LKF_CONTEXT *pContext, const char *sErrorCode)
{
	if (pContext->pStamm2001 && pContext->pStamm2001->pAllErrors)
	{
		return lkf_errorlist_code2id (pContext->pStamm2001->pAllErrors, sErrorCode);
	}
	else return -1;
}

/*************************************************************************************
** lkf_getSatzartErrorSum_Field:                                                    **
**        Liefert zu einem Errorcode eine best. Information zurück.                 **
*************************************************************************************/

_SCORING_EXPORT unsigned int lkf_getSatzartErrorSum_Field (const LKF_CONTEXT *pContext, unsigned int nCodeNr, unsigned int nFieldNr, char *sBuf, unsigned int nBufLen)
{
	if (pContext->pFilterErrorInfo && pContext->pFilterErrorInfo->nCount > nCodeNr)
	{
		return lkf_errorlist_getErrorField (pContext->pFilterErrorInfo->pErrors + nCodeNr, nFieldNr, sBuf, nBufLen);
	}
	return 0;
}

/*************************************************************************************
** lkf_getSatzartErrorSum_CodeToId:		                                            **
**        Liefert die Zeilennummer zum Errorcode zurück (oder -1).                  **
*************************************************************************************/

_SCORING_EXPORT int lkf_getSatzartErrorSum_CodeToId (const LKF_CONTEXT *pContext, const char *sErrorCode)
{
	if (pContext->pFilterErrorInfo)
	{
		return lkf_errorlist_code2id (pContext->pFilterErrorInfo, sErrorCode);
	}
	else return -1;
}

/*************************************************************************************
** lkf_context_getAllErrorCount:                                                    **
**        Liefert die Anzahl aller Errors zurück.                                   **
*************************************************************************************/

_SCORING_EXPORT unsigned int lkf_context_getAllErrorCount (const LKF_CONTEXT *pContext)
{
	if (pContext->pStamm2001 && pContext->pStamm2001->pAllErrors)
	{
		return pContext->pStamm2001->pAllErrors->nCount;
	}
	return 0;
}

/*************************************************************************************
** lkf_context_getAllErrorInfo:                                                     **
**        Liefert einen Wert zur Errorinfo.                                         **
*************************************************************************************/

_SCORING_EXPORT unsigned int lkf_context_getAllErrorInfo (const LKF_CONTEXT *pContext, unsigned int nCodeNr, unsigned int nFieldNr, char *sBuf, unsigned int nBufLen)
{
	if (pContext->pStamm2001 && pContext->pStamm2001->pAllErrors && pContext->pStamm2001->pAllErrors->nCount > nCodeNr)
	{
		return lkf_errorlist_getErrorField (pContext->pStamm2001->pAllErrors->pErrors + nCodeNr, nFieldNr, sBuf, nBufLen);
	}
	return 0;
}
