/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_i18npool.hxx"
/*************************************************************************

    Weighted Levenshtein Distance
    including wildcards
    '*' for any number (0 or more) of arbitrary characters
    '?' for exactly one arbitrary character
    escapeable with  backslash, "\*" or "\?"

    Return:
        WLD if WLD <= nLimit, else nLimit+1

    or, if bSplitCount:
        WLD if WLD <= nLimit
        -WLD if Replace and Insert and Delete <= nLimit
        else nLimit+1

    Recursive definition of WLD:

    WLD( X(i), Y(j) ) = min( WLD( X(i-1), Y(j-1) ) + p(i,j) ,
                             WLD( X(i)  , Y(j-1) ) + q      ,
                             WLD( X(i-1), Y(j)   ) + r      )

    X(i)   := the first i characters of the word X
    Y(j)   := the first j characters of the word Y
    p(i,j) := 0 if i-th character of X == j-th character of Y,
              p else

    Boundary conditions:
    WLD( X(0), Y(j) ) := j*q  (Y created by j inserts)
    WLD( X(i), Y(0) ) := i*r  (Y created by i deletes)
    WLD( X(0), Y(0) ) := 0

    Instead of recursions a dynamic algorithm is used.

    See also: German computer magazine
    c't 07/89 pages 192-208 and c't 03/94 pages 230-239

*************************************************************************/


#include <string.h>     // strlen()

#if defined( _MSC_VER )
#pragma warning(once: 4068)
#endif

#include "levdis.hxx"


#ifdef erTEST
#include <stdlib.h>
#include <stdio.h>
#include <iostream.h>
#endif

#ifdef SOLARIS
#undef min
#endif

#define LEVDISBIG   (nLimit + 1)    // Returnwert wenn Distanz > nLimit
#define LEVDISDOUBLEBUF 2048        // dadrueber wird nicht mehr gedoppelt

// Balance, aus Geschwindigkeitsgruenden ist dieses keine Funktion
// c == cpPattern[jj] == cString[ii]
// erst wird bis Fundstelle gesucht, wenn dort die Balance gleich ist, wird
// auch nach der Fundstelle verglichen
#define LEVDISBALANCE(jj,ii)                        \
{                                                   \
    if ( jj != ii )                                 \
    {                                               \
        register sal_Int32 k;                       \
        if ( jj > 0 )                               \
            for ( k=0; k < jj; k++ )                \
                if ( cpPattern[k] == c )            \
                    nBalance++;                     \
        if ( ii > 0 )                               \
            for ( k=0; k < ii; k++ )                \
                if ( cString[k] == c )              \
                    nBalance--;                     \
        if ( !nBalance )                            \
        {                                           \
            for ( k=jj+1; k < nPatternLen; k++ )    \
                if ( cpPattern[k] == c )            \
                    nBalance++;                     \
            for ( k=ii+1; k < nStringLen; k++ )     \
                if ( cString[k] == c )              \
                    nBalance--;                     \
        }                                           \
    }                                               \
}

static sal_Int32 Impl_WLD_StringLen( const sal_Unicode* pStr )
{
    const sal_Unicode* pTempStr = pStr;
    while( *pTempStr )
        pTempStr++;
    return (sal_Int32)(pTempStr-pStr);
}

#ifdef erTESTMAT
#define erTESTMATMAX 180
static int npMatrix[erTESTMATMAX][erTESTMATMAX];        // nearly 64K
#endif

// Distanz von String zu Pattern
int WLevDistance::WLD( const sal_Unicode* cString, sal_Int32 nStringLen )
{
    int nSPMin = 0;     // StrafPunkteMinimum
    int nRepS = 0;      // fuer SplitCount

#ifdef erTESTMAT
{
    for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ )
        for ( sal_Int32 c=0; c<=nPatternLen && c < erTESTMATMAX; c++ )
            npMatrix[r][c] = 99;    // Matrix initialisieren, nur visuell
}
#endif

    // Laengendifferenz von Pattern und String
    int nLenDiff = nPatternLen - nStars - nStringLen;
    // mehr Einfuegungen oder Loeschungen noetig als Limit? => raus hier
    if ( (nLenDiff * nInsQ0 > nLimit)
            || ((nStars == 0) && (nLenDiff * nDelR0 < -nLimit)) )
        return(LEVDISBIG);

    // wenn der zu vergleichende String groesser ist als das bisherige Array
    // muss dieses angepasst werden
    if ( nStringLen >= nArrayLen )
    {
        // gib ihm moeglichst mehr, damit nicht gleich naechstesmal
        // wieder realloziert werden muss
        if ( nStringLen < LEVDISDOUBLEBUF )
            nArrayLen = 2 * nStringLen;
        else
            nArrayLen = nStringLen + 1;
        npDistance = aDisMem.NewMem( nArrayLen );
#ifdef erTEST
        if ( !npDistance )
        {
            cerr << "DOOM! (Damned, Out Of Memory)" << endl;
            exit(1);
        }
#endif
    }

    // Anfangswerte der zweiten Spalte (erstes Pattern-Zeichen) berechnen
    // die erste Spalte (0-Len Pattern) ist immer 0 .. nStringLen * nInsQ0,
    // deren Minimum also 0
    if ( nPatternLen == 0 )
    {
        // Anzahl der Loeschungen, um auf Pattern zu kommen
        for ( sal_Int32 i=0; i <= nStringLen; i++ )
            npDistance[i] = i * nDelR0;
    }
    else if ( cpPattern[0] == '*' && bpPatIsWild[0] )
    {
        // statt einem '*' ist alles einsetzbar
        for ( sal_Int32 i=0; i <= nStringLen; i++ )
            npDistance[i] = 0;
    }
    else
    {
        sal_Unicode c;
        int nP;
        c = cpPattern[0];
        if ( c == '?' && bpPatIsWild[0] )
            nP = 0;     // ein '?' kann jedes Zeichen sein
        else
            // Minimum von Ersetzen und Loeschen+Einfuegen Gewichtung
            nP = Min3( nRepP0, nRepP0, nDelR0 + nInsQ0 );
        npDistance[0] = nInsQ0;     // mit einfachem Einfuegen geht's los
        npDistance[1] = nInsQ0;
        npDistance[2] = nInsQ0;
        int nReplacePos = -1;       // tristate Flag
        int nDelCnt = 0;
        for ( sal_Int32 i=1; i <= nStringLen; i++, nDelCnt += nDelR0 )
        {
            if ( cString[i-1] == c )
                nP = 0;     // Replace ab dieser Stelle ist 0
            // Loeschungen um auf Pattern zu kommen + Replace
            npDistance[i] = nDelCnt + nP;
            if ( bSplitCount )
            {
                if ( nReplacePos < 0 && nP )
                {   // diese Stelle wird ersetzt
                    nRepS++;
                    nReplacePos = i;
#ifdef erTESTMAT
                    npMatrix[i][1] = -npDistance[i];
#endif
                }
                else if ( nReplacePos > 0 && !nP )
                {
                    int nBalance = 0;   // gleiche Anzahl c
                    LEVDISBALANCE( 0, i-1 );
                    if ( !nBalance )
                    {   // einer wurde ersetzt, der ein Insert war
                        nRepS--;
#ifdef erTESTMAT
                        npMatrix[nReplacePos][1] = npDistance[nReplacePos];
#endif
                        nReplacePos = 0;
                    }
                }
            }
        }
        nSPMin = Min3( npDistance[0], npDistance[1], npDistance[2] );
    }
#ifdef erTESTMAT
{
    for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ )
    {
        npMatrix[r][0] = r * nInsQ0;
        if ( npMatrix[r][1] >= 0)
            npMatrix[r][1] = npDistance[r];
    }
}
#endif

    // Distanzmatrix berechnen
    sal_Int32 j = 0;        // fuer alle Spalten des Pattern, solange nicht Limit
    while ( (j < nPatternLen-1)
            && nSPMin <= (bSplitCount ? 2 * nLimit : nLimit) )
    {
        sal_Unicode c;
        int nP, nQ, nR, nPij, d1, d2;

        j++;
        c = cpPattern[j];
        if ( bpPatIsWild[j] )   // '*' oder '?' nicht escaped
            nP = 0;     // kann ohne Strafpunkte ersetzt werden
        else
            nP = nRepP0;
        if ( c == '*' && bpPatIsWild[j] )
        {
            nQ = 0;     // Einfuegen und Loeschen ohne Strafpunkte
            nR = 0;
        }
        else
        {
            nQ = nInsQ0;    // normale Gewichtung
            nR = nDelR0;
        }
        d2 = npDistance[0];
        // Anzahl Einfuegungen um von Null-String auf Pattern zu kommen erhoehen
        npDistance[0] = npDistance[0] + nQ;
        nSPMin = npDistance[0];
        int nReplacePos = -1;       // tristate Flag
        // fuer jede Patternspalte den String durchgehen
        for ( register sal_Int32 i=1; i <= nStringLen; i++ )
        {
            d1 = d2;                // WLD( X(i-1), Y(j-1) )
            d2 = npDistance[i];     // WLD( X(i)  , Y(j-1) )
            if ( cString[i-1] == c )
            {
                nPij = 0;           // p(i,j)
                if ( nReplacePos < 0 )
                {
                    int nBalance = 0;   // gleiche Anzahl c
                    LEVDISBALANCE( j, i-1 );
                    if ( !nBalance )
                        nReplacePos = 0;    // keine Ersetzung mehr
                }
            }
            else
                nPij = nP;
            // WLD( X(i), Y(j) ) = min( WLD( X(i-1), Y(j-1) ) + p(i,j) ,
            //                          WLD( X(i)  , Y(j-1) ) + q      ,
            //                          WLD( X(i-1), Y(j)   ) + r      )
            npDistance[i] = Min3( d1 + nPij, d2 + nQ, npDistance[i-1] + nR );
            if ( npDistance[i] < nSPMin )
                nSPMin = npDistance[i];
            if ( bSplitCount )
            {
                if ( nReplacePos < 0 && nPij && npDistance[i] == d1 + nPij )
                {   // diese Stelle wird ersetzt
                    nRepS++;
                    nReplacePos = i;
#ifdef erTESTMAT
                    npMatrix[i][j+1] = -npDistance[i];
#endif
                }
                else if ( nReplacePos > 0 && !nPij )
                {   // Zeichen in String und Pattern gleich.
                    // wenn ab hier die gleiche Anzahl dieses Zeichens
                    // sowohl in Pattern als auch in String ist, und vor
                    // dieser Stelle das Zeichen gleich oft vorkommt, war das
                    // Replace keins. Buchstabendreher werden hier erfasst
                    // und der ReplaceS zurueckgenommen, wodurch das doppelte
                    // Limit zum Tragen kommt.
                    int nBalance = 0;   // gleiche Anzahl c
                    LEVDISBALANCE( j, i-1 );
                    if ( !nBalance )
                    {   // einer wurde ersetzt, der ein Insert war
                        nRepS--;
#ifdef erTESTMAT
                        npMatrix[nReplacePos][j+1] = npDistance[nReplacePos];
#endif
                        nReplacePos = 0;
                    }
                }
            }
        }
#ifdef erTESTMAT
{
        for ( sal_Int32 r=0; r<=nStringLen && r < erTESTMATMAX; r++ )
            if ( npMatrix[r][j+1] >= 0)
                npMatrix[r][j+1] = npDistance[r];
}
#endif
    }
#ifdef erTESTSPLIT
    printf(" nRepS: %d ", nRepS );
#endif
    if ( (nSPMin <= nLimit) && (npDistance[nStringLen] <= nLimit) )
        return(npDistance[nStringLen]);
    else
    {
        if ( bSplitCount )
        {
            if ( nRepS && nLenDiff > 0 )
                nRepS -= nLenDiff;      // Inserts wurden mitgezaehlt
#ifdef erTESTSPLIT
            printf(" nRepSdiff: %d ", nRepS );
#endif
            if ( (nSPMin <= 2 * nLimit)
                    && (npDistance[nStringLen] <= 2 * nLimit)
                    && (nRepS * nRepP0 <= nLimit) )
                return( -npDistance[nStringLen] );
            return(LEVDISBIG);
        }
        return(LEVDISBIG);
    }
}



// Berechnung von nLimit,   nReplP0,    nInsQ0,     nDelR0,     bSplitCount
// aus Userwerten           nOtherX,    nShorterY,  nLongerZ,   bRelaxed
int WLevDistance::CalcLPQR( int nX, int nY, int nZ, bool bRelaxed )
{
    int nMin, nMid, nMax;
    if ( nX < 0 ) nX = 0;       // nur positive Werte
    if ( nY < 0 ) nY = 0;
    if ( nZ < 0 ) nZ = 0;
    if ( 0 == (nMin = Min3( nX, nY, nZ )) )     // mindestens einer 0
    {
        nMax = Max3( nX, nY, nZ );      // entweder 0 bei drei 0 oder Max
        if ( 0 == (nMid = Mid3( nX, nY, nZ )) )     // sogar zwei 0
            nLimit = nMax;  // entweder 0 oder einziger >0
        else        // einer 0
            nLimit = KGV( nMid, nMax );
    }
    else        // alle drei nicht 0
        nLimit = KGV( KGV( nX, nY ), nZ );
    nRepP0 = ( nX ? nLimit / nX : nLimit + 1 );
    nInsQ0 = ( nY ? nLimit / nY : nLimit + 1 );
    nDelR0 = ( nZ ? nLimit / nZ : nLimit + 1 );
    bSplitCount = bRelaxed;
    return( nLimit );
}



// Groesster Gemeinsamer Teiler nach Euklid (Kettendivision)
// Sonderfall: 0 und irgendwas geben 1
int WLevDistance::GGT( int a, int b )
{
    if ( !a || !b )
        return 1;
    if ( a < 0 ) a = -a;
    if ( b < 0 ) b = -b;
    do
    {
        if ( a > b )
            a -= int(a / b) * b;
        else
            b -= int(b / a) * a;
    } while ( a && b );
    return( a ? a : b);
}



// Kleinstes Gemeinsames Vielfaches: a * b / GGT(a,b)
int WLevDistance::KGV( int a, int b )
{
    if ( a > b )    // Ueberlauf unwahrscheinlicher machen
        return( (a / GGT(a,b)) * b );
    else
        return( (b / GGT(a,b)) * a );
}


// Minimum von drei Werten
inline int WLevDistance::Min3( int x, int y, int z )
{
    if ( x < y )
        return( x < z ? x : z );
    else
        return( y < z ? y : z );
}



// mittlerer von drei Werten
int WLevDistance::Mid3( int x, int y, int z )
{
    int min = Min3(x,y,z);
    if ( x == min )
        return( y < z ? y : z);
    else if ( y == min )
        return( x < z ? x : z);
    else        // z == min
        return( x < y ? x : y);
}



// Maximum von drei Werten
int WLevDistance::Max3( int x, int y, int z )
{
    if ( x > y )
        return( x > z ? x : z );
    else
        return( y > z ? y : z );
}



// Daten aus CTor initialisieren
void WLevDistance::InitData( const sal_Unicode* cPattern )
{
    cpPattern = aPatMem.GetcPtr();
    bpPatIsWild = aPatMem.GetbPtr();
    npDistance = aDisMem.GetPtr();
    nStars = 0;
    const sal_Unicode* cp1 = cPattern;
    sal_Unicode* cp2 = cpPattern;
    bool* bp = bpPatIsWild;
    // Pattern kopieren, Sternchen zaehlen, escaped Jokers
    while ( *cp1 )
    {
        if ( *cp1 == '\\' )     // maybe escaped
        {
            if ( *(cp1+1) == '*' || *(cp1+1) == '?' )   // naechstes Joker?
            {
                cp1++;          // skip '\\'
                nPatternLen--;
            }
            *bp++ = false;
        }
        else if ( *cp1 == '*' || *cp1 == '?' )      // Joker
        {
            if ( *cp1 == '*' )
                nStars++;       // Sternchenzaehler erhoehen
            *bp++ = true;
        }
        else
            *bp++ = false;
        *cp2++ = *cp1++;
    }
    *cp2 = '\0';
}


// CTor

#ifdef erTEST

WLevDistance::WLevDistance( const ::rtl::OUString& rPattern ) :
    nPatternLen( rPattern.getLength() ),
    aPatMem( nPatternLen + 1 ),
    nArrayLen( nPatternLen + 1 ),
    aDisMem( nArrayLen ),
    nLimit( LEVDISDEFAULTLIMIT ),
    nRepP0( LEVDISDEFAULT_P0 ),
    nInsQ0( LEVDISDEFAULT_Q0 ),
    nDelR0( LEVDISDEFAULT_R0 ),
    bSplitCount( false )
{
    InitData( rPattern.getStr() );
}

#endif  // erTEST


WLevDistance::WLevDistance( const sal_Unicode* cPattern,
                            int nOtherX, int nShorterY, int nLongerZ,
                            bool bRelaxed ) :
    nPatternLen( Impl_WLD_StringLen(cPattern) ),
    aPatMem( nPatternLen + 1 ),
    nArrayLen( nPatternLen + 1 ),
    aDisMem( nArrayLen )
{
    InitData( cPattern );
    CalcLPQR( nOtherX, nShorterY, nLongerZ, bRelaxed );
}


// CopyCTor
WLevDistance::WLevDistance( const WLevDistance& rWLD ) :
    nPatternLen( rWLD.nPatternLen ),
    aPatMem( nPatternLen + 1 ),
    nArrayLen( nPatternLen + 1 ),
    aDisMem( nArrayLen ),
    nLimit( rWLD.nLimit ),
    nRepP0( rWLD.nRepP0 ),
    nInsQ0( rWLD.nInsQ0 ),
    nDelR0( rWLD.nDelR0 ),
    nStars( rWLD.nStars ),
    bSplitCount( rWLD.bSplitCount )
{
    cpPattern = aPatMem.GetcPtr();
    bpPatIsWild = aPatMem.GetbPtr();
    npDistance = aDisMem.GetPtr();
    sal_Int32 i;
    for ( i=0; i<nPatternLen; i++ )
    {
        cpPattern[i] = rWLD.cpPattern[i];
        bpPatIsWild[i] = rWLD.bpPatIsWild[i];
    }
    cpPattern[i] = '\0';
}


// DTor
WLevDistance::~WLevDistance()
{
}

/*************************************************************************
 * Test
 *************************************************************************/

#ifdef erTEST

#define LINESIZE 1000
typedef char MAXSTRING [LINESIZE+1];

#ifdef erTESTMAT

void WLevDistance::ShowMatrix( const sal_Unicode* cString )
{
    sal_Int32 r, c, l = Impl_WLD_StringLen(cString);
    printf("   |   ");
    for ( c=0; c<nPatternLen; c++ )
#error Error: conversion from sal_Unicode to char needed!
        printf( " %c ", cpPattern[c] );
    printf("\n---+---");
    for ( c=0; c<nPatternLen; c++ )
        printf( "---" );
    for ( r=0; r<=l && r < erTESTMATMAX; r++ )
    {
#error Error: conversion from sal_Unicode to char needed!
        printf( "\n %c |", ( r==0 ? ' ' : cString[r-1] ) );
        for ( c=0; c<=nPatternLen && c < erTESTMATMAX; c++ )
            printf( "%2d ", npMatrix[r][c] );
    }
    printf("\n\n");
}

#endif  // erTESTMAT

// Delimiter fuer Token, \t Tab bleibt fuer immer an der ersten Stelle
MAXSTRING cDelim = "\t, ;(){}[]<>&=+-/%!|.\\'\"~";

void WLevDistance::ShowTest()
{
    printf("  \n");
#error Error: conversion from sal_Unicode to char needed!
    printf(" a *cpPattern . . . . : %s\n", cpPattern);
    printf(" b *bpPatIsWild . . . : ");
    for ( sal_Int32 i=0; i<nPatternLen; i++ )
        printf("%d", bpPatIsWild[i]);
    printf("\n");
    printf(" c nPatternLen  . . . : %d\n", (int)nPatternLen);
    printf(" d nStars . . . . . . : %d\n", nStars);
    printf(" e nLimit . . . . . . : %d\n", nLimit);
    printf(" f nRepP0 (Ersetzen)  : %d\n", nRepP0);
    printf(" g nInsQ0 (Einfuegen) : %d\n", nInsQ0);
    printf(" h nDelR0 (Loeschen)  : %d\n", nDelR0);
    printf(" i bSplitCount  . . . : %d\n", bSplitCount);
#error Error: conversion from sal_Unicode to char needed!
    printf(" j cDelim . . . . . . : '%s'\n", cDelim);
    printf(" ~\n");
}

inline bool IsDelim( char c )
{
    char* cp = cDelim;
    while ( *cp )
        if ( *cp++ == c )
            return( true );
    return( false );
}

MAXSTRING cString, cLine, cIgString;

int main( int argc, char **argv )
{
    int nLim, nP0, nQ0, nR0, nX, nY, nZ;
    int args = 0;
    bool IgnoreCase = false, Direct = false, bStrict = false;
    WLevDistance* pTest;
    if ( argc < 2 )
    {
        printf("%s  Syntax:\n"
            " ... [-i] cPattern [nOtherX, nShorterY, nLongerZ [bStrict [cDelim]]] [<stdin] [>stdout]\n"
            " ...  -d  cPattern [nLimit [nRepP0 nInsQ0 nDelR0 [cDelim]]] [<stdin] [>stdout]\n"
            , argv[0]);
        exit(1);
    }
    if ( *argv[1] == '-' )
    {
        args++;
        argc--;
        switch ( *(argv[1]+1) )
        {
            case 'i':
            {
                IgnoreCase = true;
                char* cp = argv[args+1];
                while ( (*cp = tolower( *cp )) != 0 )
                    cp++;
        break;
            }
            case 'd':
                Direct = true;
        break;
        }
    }
    if ( Direct )
    {
        if ( argc > 2 )
            nLim = atoi(argv[args+2]);
        else
            nLim = LEVDISDEFAULTLIMIT;
        if ( argc > 3 )
        {
            nP0 = atoi(argv[args+3]);
            nQ0 = atoi(argv[args+4]);
            nR0 = atoi(argv[args+5]);
        }
        else
        {
            nP0 = LEVDISDEFAULT_P0;
            nQ0 = LEVDISDEFAULT_Q0;
            nR0 = LEVDISDEFAULT_R0;
        }
        if ( argc > 6 )
        {
            strncpy( cDelim+1, argv[args+6], LINESIZE );    // \t Tab always remains
            cDelim[LINESIZE-1] = 0;
        }
    }
    else
    {
        if ( argc > 2 )
        {
            nX = atoi(argv[args+2]);
            nY = atoi(argv[args+3]);
            nZ = atoi(argv[args+4]);
        }
        else
        {
            nX = LEVDISDEFAULT_XOTHER;
            nY = LEVDISDEFAULT_YSHORTER;
            nZ = LEVDISDEFAULT_ZLONGER;
        }
        if ( argc > 5 )
            bStrict = atoi(argv[args+5]);
        if ( argc > 6 )
        {
            strncpy( cDelim+1, argv[args+6], LINESIZE );    // \t Tab always remains
            cDelim[LINESIZE-1] = 0;
        }
    }
    if ( Direct )
    {
#error Error: conversion from char to OUString needed!
        pTest = new WLevDistance( argv[args+1] );
#ifdef erTESTDEFAULT
        pTest->ShowTest();
#endif
        pTest->SetLimit( nLim );
        pTest->SetReplaceP0( nP0 );
        pTest->SetInsertQ0( nQ0 );
        pTest->SetDeleteR0( nR0 );
    }
    else
    {
#error Error: conversion from char to sal_Unicode needed!
        pTest = new WLevDistance( argv[args+1], nX, nY, nZ, !bStrict );
#ifdef erTESTCCTOR
        WLevDistance aTmp( *pTest );
        aTmp.ShowTest();
#endif
        nLim = pTest->GetLimit();
    }
    pTest->ShowTest();
    do
    {
        char* cp1, *cp2;
        static long unsigned int nLine = 0;
        cp1 = cLine;
        cin.getline( cLine, LINESIZE ) ;
        nLine++;
        while ( *cp1 )
        {
            while ( *cp1 && IsDelim(*cp1) )
                cp1++;
            cp2 = cString;
            while ( *cp1 && !IsDelim(*cp1) )
                *cp2++ = *cp1++;
            *cp2 = '\0';
            while ( *cp1 && IsDelim(*cp1) )
                cp1++;
            if ( *cString )
            {
                int ret;
                if ( IgnoreCase )
                {
                    char* cpi1 = cString;
                    char* cpi2 = cIgString;
                    while ( *cpi1 )
                        *cpi2++ = tolower( *cpi1++ );
                    *cpi2 = '\0';
#error Error: conversion from char to OUString / sal_Unicode,length needed!
                    ret = pTest->WLD( cIgString );
                }
                else
#error Error: conversion from char to OUString / sal_Unicode,length needed!
                    ret = pTest->WLD( cString );
#ifdef erTESTMAT
                printf("\n# %3d : %s\n", ret, cString);
#error Error: conversion from char to sal_Unicode needed!
                pTest->ShowMatrix( cString );
#else
                if ( ret <= nLim )
                    printf("# %3d : %s\t(line %lu)\t%s\n", ret, cString, nLine, cLine);
#endif
            }
        }
    } while ( !cin.eof() );
    return 0;
}

#endif  // erTEST

