/*
 * International Chemical Identifier (InChI)
 * Version 1
 * Software version 1.04
 * September 9, 2011
 *
 * The InChI library and programs are free software developed under the
 * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
 * Originally developed at NIST. Modifications and additions by IUPAC 
 * and the InChI Trust.
 *
 * IUPAC/InChI-Trust Licence for the International Chemical Identifier (InChI) 
 * Software version 1.0.
 * Copyright (C) IUPAC and InChI Trust Limited
 * 
 * This library is free software; you can redistribute it and/or modify it under the 
 * terms of the IUPAC/InChI Trust Licence for the International Chemical Identifier 
 * (InChI) Software version 1.0; either version 1.0 of the License, or 
 * (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * See the IUPAC/InChI Trust Licence for the International Chemical Identifier (InChI) 
 * Software version 1.0 for more details.
 * 
 * You should have received a copy of the IUPAC/InChI Trust Licence for the 
 * International Chemical Identifier (InChI) Software version 1.0 along with 
 * this library; if not, write to:
 * 
 * The InChI Trust
 * c/o FIZ CHEMIE Berlin
 * Franklinstrasse 11
 * 10587 Berlin
 * GERMANY
 * 
 */


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

/*#define CHECK_WIN32_VC_HEAP*/
#include "mode.h"

#if ( READ_INCHI_STRING == 1 )

#include "ichi.h"
#include "ichitime.h"

#include "inpdef.h"
#include "ichimain.h"
#include "ichierr.h"
#include "incomdef.h"
#include "ichiring.h"
#include "extr_ct.h"
#include "ichitaut.h"
#include "ichinorm.h"
#include "util.h"

#include "ichicomp.h"
#include "ichister.h"

#include "ichi_bns.h"

#include "strutil.h"

#include "ichirvrs.h"

#define INC_ADD_EDGE 64

/* local types */

/* types for TgDiffHChgFH */
#define fNumRPosChgH 0 /* number of positive charges on endpoints that have H in at2[] */
#define fNumRPosChgU 1 /* number of positive charges on endpoints that have no H in at2[] */
#define fNumRNegChgO 2 /* number of negative charges on O endpoints */
#define fNumRNegChgN 3 /* number of negative charges on N endpoints */
#define fNumRNeutrlH 4 /* number of neutral endp that have H in at2[] */

#define fNumNPosChgH 5 /* number of positive charges on endpoints that have H in atf[] */
#define fNumNPosChgU 6 /* number of positive charges on endpoints that have no H in atf[] */
#define fNumNNegChgO 7 /* number of negative charges on O endpoints */
#define fNumNNegChgN 8 /* number of negative charges on N endpoints */
#define fNumNNeutrlH 9 /* number of neutral endp that have H in atf[] */

#define fNumAllChgT 10 /* total  number of fNum... */

typedef struct tagTgDiffHChgFH {
    short  itg; /* t-group index; endpoint = itg+1 */
    short  nNumHInchi;  /* number of H in t-group from orig. InChI */
    short  nNumHRevrs;  /* number of H in at2[] */
    short  nNumHNorml;  /* number of H in Normalized atfMobile_H_Revrs[] */
    short  nNumMInchi;  /* number of (-) in InChI */
    short  nNumMRevrs;  /* number of (-) in at2[] */
    short  nNumMNorml;  /* number of (-) in atf[] */
    short  nNumPRevrs;  /* number of (+) in at2[] */
    short  nNumPNorml;  /* number of (+) in Normalized atfMobile_H_Revrs[] */
    short n[fNumAllChgT]; /* all numbers */
    short i[fNumAllChgT]; /* all indices */
} TgDiffHChgFH;

/* local prototypes */
static int FillTgDiffHChgFH( TgDiffHChgFH tdhc[], int max_tdhc, inp_ATOM at2[], inp_ATOM atf[],
                            AT_NUMB  *nCanon2AtnoRevrs, VAL_AT *pVA, T_GROUP_INFO *ti, EDGE_LIST *pAtomIndList );


/************************************************************/
int bHas_N_V( inp_ATOM *at2, int num_atoms )
{
    static U_CHAR el_number_N;
    int i, num_found = 0;
    if ( !el_number_N ) {
        el_number_N = get_periodic_table_number( "N" );
    }
    for ( i = 0; i < num_atoms; i ++ ) {
        if ( at2[i].el_number == el_number_N && !at2[i].charge &&
             !at2[i].num_H && !at2[i].radical &&
             at2[i].chem_bonds_valence == 5 &&
             (at2[i].valence==3) ) {
            num_found ++;
        }
    }
    return num_found;
}
/*************************************************************************************/
int FillTgDiffHChgFH( TgDiffHChgFH tdhc[], int max_tdhc, inp_ATOM at2[],
                      inp_ATOM atf[], AT_NUMB  *nCanon2AtnoRevrs, VAL_AT *pVA,
                      T_GROUP_INFO *ti, EDGE_LIST *pAtomIndList )
{

    int i, j, iat, itg, itg_prev, num, itg_out, bOverflow;
    EDGE_LIST IndList;   /* type, itg */
    TgDiffHChgFH cur_tdhc;
    AT_NUMB    *pEndp0;
    inp_ATOM   *at2i, *atfi;
    int         typeR, typeN, type, ret = 0, nCurIndListLen;

    AllocEdgeList( &IndList, EDGE_LIST_CLEAR );
    pAtomIndList->num_edges = 0;
    itg_out = 0;
    bOverflow = 0;
    memset( tdhc, 0, max_tdhc * sizeof(tdhc[0]) );

    for ( itg = 0; itg < ti->num_t_groups; itg ++ ) {
        memset( &cur_tdhc, 0, sizeof(cur_tdhc) );

        cur_tdhc.itg = itg;
        cur_tdhc.nNumHInchi = ti->t_group[itg].num[0] - ti->t_group[itg].num[1];
        cur_tdhc.nNumMInchi = ti->t_group[itg].num[1];
        
        pEndp0 = ti->nEndpointAtomNumber + ti->t_group[itg].nFirstEndpointAtNoPos;
        nCurIndListLen = IndList.num_edges;
        for ( j = 0; j < ti->t_group[itg].nNumEndpoints; j ++ ) {
            i = pEndp0[j];
            iat = nCanon2AtnoRevrs[i];
            
            at2i = at2 + iat;
            atfi = atf + iat;
            
            typeR = typeN = -1;
            if ( at2i->charge == 1 ) {
                if ( at2i->num_H ) {
                    typeR = fNumRPosChgH;
                } else {
                    typeR = fNumRPosChgU;
                }
                cur_tdhc.nNumPRevrs ++;
            } else
            if ( at2i->charge == -1 ) {
                if ( pVA[iat].cNumValenceElectrons == 6) {
                    typeR = fNumRNegChgO;
                } else
                if ( pVA[iat].cNumValenceElectrons == 5) {
                    typeR = fNumRNegChgN;
                }
                cur_tdhc.nNumMRevrs ++;
            } else
            if ( at2i->num_H && at2i->valence == at2i->chem_bonds_valence ) {
                typeR = fNumRNeutrlH;
            }
            cur_tdhc.nNumHRevrs += at2i->num_H;

            if ( atfi->charge == 1 ) {
                if ( atfi->num_H ) {
                    typeN = fNumNPosChgH;
                } else {
                    typeN = fNumNPosChgU;
                }
                cur_tdhc.nNumPNorml ++;
            } else
            if ( atfi->charge == -1 ) {
                if ( pVA[iat].cNumValenceElectrons == 6) {
                    typeN = fNumNNegChgO;
                } else
                if ( pVA[iat].cNumValenceElectrons == 5) {
                    typeN = fNumNNegChgN;
                }
                cur_tdhc.nNumMNorml ++;
            } else
            if ( atfi->num_H && atfi->valence == atfi->chem_bonds_valence ) {
                typeN = fNumNNeutrlH;
            }
            cur_tdhc.nNumHNorml += atfi->num_H;
            if ( at2[iat].charge < 0 || 0 < pVA[iat].nCPlusGroupEdge ) {
                if ( typeR >= 0 && (
                     (ret = AddToEdgeList( &IndList, typeR, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &IndList, itg, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &IndList, iat, INC_ADD_EDGE )) ) ) {
                    goto exit_function;
                }
                if ( typeN >= 0 && (
                     (ret = AddToEdgeList( &IndList, typeN, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &IndList, itg, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &IndList, iat, INC_ADD_EDGE )) ) ) {
                    goto exit_function;
                }
            }

        }
        if ( cur_tdhc.nNumHNorml == cur_tdhc.nNumHInchi &&
             cur_tdhc.nNumMNorml == cur_tdhc.nNumMInchi ) {
            IndList.num_edges = nCurIndListLen; /* t-group seems to be correct */
            continue;
        }
        if ( itg_out < max_tdhc ) {
            tdhc[itg_out ++] = cur_tdhc;
        } else {
            bOverflow |= 1;
            IndList.num_edges = nCurIndListLen;
            break;
        }
    }
    /* fill out atom index list */
    if ( itg_out ) {
        itg_prev = IndList.pnEdges[1]; /* the 1st saved t-group number */
        for ( type = 0; type < fNumAllChgT; type ++ ) {
            j = 0;
            for ( i = 0; i < itg_out; i ++ ) {
                num = 0;
                itg = tdhc[i].itg;
                tdhc[i].i[type] = -999; /* empty */
                while( IndList.pnEdges[j+1] == itg ) {
                    if ( IndList.pnEdges[j] == type ) {
                        if ( !num ++ ) {
                            tdhc[i].i[type] = pAtomIndList->num_edges;
                        }
                        if ( (ret = AddToEdgeList( pAtomIndList, IndList.pnEdges[j+2], INC_ADD_EDGE )) ) {
                            goto exit_function;
                        }
                    }
                    j += 3;
                }
                tdhc[i].n[type] = num;
            }
        }
    }
    ret = itg_out;
exit_function:
    AllocEdgeList( &IndList, EDGE_LIST_FREE );
    return ret;

/*
#undef fNumRPosChgH
#undef fNumRPosChgU
#undef fNumRNegChgO
#undef fNumRNegChgN

#undef fNumNPosChgH
#undef fNumNPosChgU
#undef fNumNNegChgO
#undef fNumNNegChgN

#undef fNumAllChgT    
*/
}

/***********************************************************************************************/
int FixFixedHRestoredStructure(ICHICONST INPUT_PARMS *ip, STRUCT_DATA *sd, BN_STRUCT *pBNS, BN_DATA *pBD,
                        StrFromINChI *pStruct, inp_ATOM *at, inp_ATOM *at2, inp_ATOM *at3, VAL_AT *pVA,
                        ALL_TC_GROUPS *pTCGroups, T_GROUP_INFO **ppt_group_info, inp_ATOM **ppat_norm,
                        inp_ATOM **ppat_prep, INChI *pInChI[], long num_inp, int bHasSomeFixedH,
                        int *pnNumRunBNS, int *pnTotalDelta, int forbidden_edge_mask, int forbidden_stereo_edge_mask)
{
    /*--------- process extra or missing Fixed-H on non-tautomeric atoms ------*/
    /* at2 should be the most recently restored atom, Fixed-H */
    int i, j, k, delta, num_try, tot_succes, cur_success, ret = 0, bAllowedNFlowerEdges=0, num_zero_ret;
    CMP2FHINCHI c2i;
    CMP2FHINCHI *pc2i = &c2i;

    EDGE_LIST AllChargeEdges, CurrEdges, SFlowerEdges, NFlowerEdges, OtherNFlowerEdges, FixedLargeRingStereoEdges;
    EDGE_LIST AllBondEdges;
    
    EdgeIndex e;
    BNS_EDGE  *pe;
    Vertex v1, v2;
    BNS_VERTEX *pv1, *pv2;

    Vertex     vPathStart, vPathEnd;
    int        nPathLen, nDeltaH, nDeltaCharge, nNumVisitedAtoms;

    int        nNumRunBNS = 0, forbidden_edge_mask_inv = ~forbidden_edge_mask;

    INCHI_HEAPCHK

    AllocEdgeList( &AllChargeEdges, EDGE_LIST_CLEAR );
    AllocEdgeList( &CurrEdges, EDGE_LIST_CLEAR );
    AllocEdgeList( &NFlowerEdges, EDGE_LIST_CLEAR );
    AllocEdgeList( &SFlowerEdges, EDGE_LIST_CLEAR );
    AllocEdgeList( &OtherNFlowerEdges, EDGE_LIST_CLEAR );
    AllocEdgeList( &FixedLargeRingStereoEdges, EDGE_LIST_CLEAR );
    AllocEdgeList( &AllBondEdges, EDGE_LIST_CLEAR );

    tot_succes = 0;
    
    if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
        goto exit_function;  /* no fixed-H found */
    }

    for ( i = 0; i < pStruct->num_atoms; i ++ ) {
        if ( (e=pVA[i].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
             (ret = AddToEdgeList( &AllChargeEdges, e, INC_ADD_EDGE )) ) {
            goto exit_function;
        }
        if ( (e=pVA[i].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
            if ( (ret = AddToEdgeList( &AllChargeEdges, e, INC_ADD_EDGE )) ) {
                goto exit_function;
            }

            /* in addition, disallow N(V) creation by forbidding charge flower edge that has flow=1 */
            if ( pVA[i].cNumValenceElectrons == 5 && !pVA[i].cMetal && /* N, P, As */
                 NO_VERTEX != (j = GetChargeFlowerUpperEdge( pBNS, pVA, e ))) {

                if ( pBNS->edge[j].forbidden ) {
                    continue;
                }

                if ( pBNS->edge[j].flow ) {
                    if ( (ret = AddToEdgeList( &AllChargeEdges, j, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                    if ( (ret = AddToEdgeList( &NFlowerEdges, j, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                } else {
                    if ( (ret = AddToEdgeList( &OtherNFlowerEdges, j, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                }
            } else
            /* in addition, disallow N(V) creation by forbidding charge flower edge that has flow=1 */
            if ( pVA[i].cNumValenceElectrons == 6 && !pVA[i].cMetal && /* N, P, As */
                 NO_VERTEX != (j = GetChargeFlowerUpperEdge( pBNS, pVA, e ))) {

                if ( pBNS->edge[j].forbidden ) {
                    continue;
                }

                if ( pBNS->edge[j].flow ) {
                    if ( (ret = AddToEdgeList( &SFlowerEdges, j, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                }
            }

        }
        for ( j = 0; j < at2[i].valence; j ++ ) {
            k = at2[i].neighbor[j];
            if ( k < i && !pBNS->edge[e=pBNS->vert[i].iedge[j]].forbidden ) {
                if ( (ret = AddToEdgeList( &AllBondEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
    }
    if ( forbidden_stereo_edge_mask ) {
        for ( i = 0; i < pStruct->num_atoms; i ++ ) {
            for ( j = 0; j < at2[i].valence; j ++ ) {
                if ( pBNS->edge[k = pBNS->vert[i].iedge[j]].forbidden == forbidden_stereo_edge_mask ) {
                    int nMinRingSize = is_bond_in_Nmax_memb_ring( at2, i, j, pStruct->pbfsq->q,
                                                             pStruct->pbfsq->nAtomLevel,
                                                             pStruct->pbfsq->cSource, 99 /* max ring size */ );
                    if ( 0 < nMinRingSize && (ret = AddToEdgeList( &FixedLargeRingStereoEdges, k, INC_ADD_EDGE ))) {
                        goto exit_function;
                    }
                }
            }
        }
    }

    INCHI_HEAPCHK
    if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
        goto exit_function;
    }
    INCHI_HEAPCHK
    if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
        goto exit_function;
    }

    INCHI_HEAPCHK

    if ( !pc2i->bHasDifference ||
         (!pc2i->len_c2at && pc2i->nNumTgRevrs == pc2i->nNumTgInChI &&
         pc2i->nNumEndpRevrs == pc2i->nNumRemHInChI &&
         pc2i->nNumEndpRevrs == pc2i->nNumEndpInChI &&
         !pc2i->nNumTgDiffMinus && !pc2i->nNumTgDiffH) ) {
        goto exit_function; /* nothing to do */
    }

    /*goto exit_function;*/ /* debug only*/

    if ( pc2i->len_c2at >= 2 ) {
        /*----------------------------------------------------*/
        /* case 01: restored: O=AB-O(-)  original:  (-)O-AB=O */
        /* FixH:              0    -1                 -1    0 */
        /* MobH:              0     1                  1    0 */
        /*                         non-taut      non-taut     */
        /* O = O, S, Se; charged atoms O are not tautomeric   */
        /* Solution: move (-) from B-O(-) to O=A              */
        /*----------------------------------------------------*/
        int num_DB_O = 0, num_SB_O_Minus = 0, iat;
        short iat_DB_O[MAX_DIFF_FIXH], iat_SB_O_Minus[MAX_DIFF_FIXH];
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( pc2i->c2at[i].nValElectr == 6 /* && !pc2i->c2at[i].endptInChI -- mod#1*/ &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                if ( /* orig. InChI info: */
                     num_SB_O_Minus < MAX_DIFF_FIXH && 
                     pc2i->c2at[i].nFixHInChI ==  0 && pc2i->c2at[i].nMobHInChI == 0 &&
                     /* reversed structure info: */
                     pc2i->c2at[i].nFixHRevrs == -1 && pc2i->c2at[i].nMobHRevrs == 1 &&
                     pc2i->c2at[i].nAtChargeRevrs == -1 && !at2[iat].num_H && /* at2 is Fixed-H */
                     at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 1 ) {
                    iat_SB_O_Minus[num_SB_O_Minus ++] = iat;
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                } else
                if ( /* orig. InChI info: */
                     num_DB_O < MAX_DIFF_FIXH &&
                     pc2i->c2at[i].nFixHInChI == -1 && pc2i->c2at[i].nMobHInChI ==  1 &&
                     /* reversed structure info: */
                     pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs ==  0 &&
                     pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                     at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 2 ) {
                    iat_DB_O[num_DB_O ++] = iat;
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_O_Minus, num_DB_O )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_O_Minus && cur_success < num_try; i ++ ) {
                iat = iat_SB_O_Minus[i];
                pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta; /* remove (-) from AB-O(-) */
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Added (-)charge to O=AB => nDeltaCharge == -1 */
                    /* Flow change on pe (-)charge edge (atom B-O(-)) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 01 */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
            CurrEdges.num_edges = 0; /* clear current edge list */
        }
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at >= 1 ) {
        /*--------------------------------------------------------------*/
        /* case 02: restored: -O(+)=AB-NH2  original:  -O-AB=NH2(+)     */
        /* FixH:               0        0               0      1        */
        /* MobH:               0        2               0      1        */
        /* O = P, As, Sb, O, S, Se, F, Cl, Br, I; not taut. in InChI    */
        /* N = N, O, S, Se, Te; has H; tautomeric or not tautomeric     */
        /* Solution: move (+) from O(+) to NH2                          */
        /*--------------------------------------------------------------*/
        int num_DB_O_Plus = 0, num_SB_NH = 0, iat;
        short iat_DB_O_Plus[MAX_DIFF_FIXH], iat_SB_NH[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : NULL;
        cur_success = 0;
        num_zero_ret = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: =NH2(+), =OH(+) */
                 num_SB_NH < MAX_DIFF_FIXH &&
                 ((pc2i->c2at[i].nValElectr == 5 && pc2i->c2at[i].nPeriodNum == 1) ||
                  pc2i->c2at[i].nValElectr == 6 ) /* N, O, S, Se, Te */ &&
                 /*!pc2i->c2at[i].endptInChI &&*/ /* <=== relaxation */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI>0 /*== 1 --modification#2*/ && /*pc2i->c2at[i].nMobHInChI ==  1 &&*/
                 /* reversed structure info: */
                 pc2i->c2at[i].nFixHRevrs ==  0 && /* pc2i->c2at[i].nMobHRevrs == 0 &&*/
                 pc2i->c2at[i].nAtChargeRevrs == 0 && at2[iat].num_H &&
                 at2[iat].valence == at2[iat].chem_bonds_valence ) {
                iat_SB_NH[num_SB_NH ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom: charge=+1, no H, has double bond, P, As, O, S, Se, Te, F, Cl, Br, I */
                 num_DB_O_Plus < MAX_DIFF_FIXH &&
                 at2[iat].charge == 1 && !at2[iat].num_H &&
                 at2[iat].valence < at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 (pVA[iat].cNumValenceElectrons == 6 || pVA[iat].cNumValenceElectrons == 7 ||
                  (pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber > 1)) &&
                 /* in orig.InChI: not an endpoint, has no H */
                 !pStruct->endpoint[i] && 
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                iat_DB_O_Plus[num_DB_O_Plus ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_DB_O_Plus, num_SB_NH )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
repeat_02_allow_NV:
            for ( i = 0; i < num_SB_NH && cur_success < num_try; i ++ ) {
                iat = iat_SB_NH[i];
                pe   = pBNS->edge + pVA[iat].nCPlusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
                
                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == -1 ) {
                    /* Removed charge from O(+) => nDeltaCharge == -1 */
                    /* Flow change on pe (+)charge edge (atom NH2) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 02 */
                    }
                } else {
                    num_zero_ret += !ret;
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            if ( num_zero_ret == num_try && !bAllowedNFlowerEdges && NFlowerEdges.num_edges ) {
                RemoveForbiddenEdgeMask( pBNS, &NFlowerEdges, forbidden_edge_mask  );
                bAllowedNFlowerEdges = 1;
                goto repeat_02_allow_NV;
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
            bAllowedNFlowerEdges = 0;
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at >= 1 && pc2i->nNumTgRevrs == 1 &&
         (pc2i->nNumEndpRevrs > pc2i->nNumEndpInChI || pc2i->nNumTgInChI > 1) /* ADP in Revrs */ ) {
        /*--------------------------------------------------------------*/
        /* case 03: restored: -N(-)-AB=O    original:  -N=AB-O(-)       */
        /* FixH:               0       0                0     -1        */
        /* MobH:               0       0                0      1        */
        /* O = O, S, Se; N = N;                                         */
        /* restored atoms are tautomeric; original atoms are not taut.  */
        /* restored struct has 1 t-group; original has less endpoints   */
        /*                                and possibly >1 t-groups      */  
        /* Solution: move (-) from N(-) to =O                           */
        /*           these atoms are tautomeric in restored structure   */
        /*--------------------------------------------------------------*/
        int num_SB_N_Minus = 0, num_DB_O = 0, iat;
        short iat_SB_N_Minus[MAX_DIFF_FIXH], iat_DB_O[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        /*
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: -O(-) */
                 num_DB_O < MAX_DIFF_FIXH &&
                 pc2i->c2at[i].nValElectr == 6 /* O, S, Se, Te */ &&
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == -1 && pc2i->c2at[i].nMobHInChI ==  1 &&
                 /* reversed structure info: */
                 pc2i->c2at[i].endptRevrs &&
                 pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs == 0 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 2 ) {
                iat_DB_O[num_DB_O ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom N: charge=-1, no H, has no double bond, endpoint */
                 num_SB_N_Minus < MAX_DIFF_FIXH &&
                 at2[iat].charge == -1 && /*!at2[iat].num_H &&*/
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1 &&
                 at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint &&
                 /* in orig.InChI: not an endpoint, has no H */
                 /* !pStruct->endpoint[i] && */
               /*  
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                */
                 /* has (-) edge */
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                iat_SB_N_Minus[num_SB_N_Minus ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_N_Minus, num_DB_O )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_N_Minus && cur_success < num_try; i ++ ) {
                iat = iat_SB_N_Minus[i];
                pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1; /* 2006-03-03: changed from CPlusGroupEdge */
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Added (-) charge to =O => nDeltaCharge == 1 */
                    /* Flow change on pe (-)charge edge (atom -N(-)-) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 03 */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }
    
    if ( pc2i->nNumTgRevrs == 1 && /* pc2i->nNumRemHInChI < 0 &&*/
         (pc2i->nNumEndpRevrs > pc2i->nNumEndpInChI || pc2i->nNumTgInChI > 1) /* ADP in Revrs */ ) {
        /*--------------------------------------------------------------*/
        /* case 03a:restored: -N(-)-AB=O    original:  -N=AB-O(-)       */
        /* FixH:               0       0                0      0        */
        /* MobH:               0       0                0      0        */
        /* O = O, S, Se; N = N;                              taut       */
        /* restored atoms are tautomeric; original atom is; N may be.   */
        /* restored struct has 1 t-group; original has less endpoints   */
        /*                                and possibly >1 t-groups      */  
        /* Solution: move (-) from N(-) to =O                           */
        /*           these atoms are tautomeric in restored structure   */
        /*--------------------------------------------------------------*/
        int num_SB_N_Minus = 0, num_DB_O = 0, iat;
        short iat_SB_N_Minus[MAX_DIFF_FIXH], iat_DB_O[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        S_CHAR   *pnMobHInChI = (pInChI[1] && pInChI[1]->nNum_H)? pInChI[1]->nNum_H :
                                (pInChI[0] && pInChI[0]->nNum_H)? pInChI[0]->nNum_H : NULL;
        S_CHAR   *pnFixHInChI = pStruct->fixed_H;

        cur_success = 0;
        CurrEdges.num_edges = 0;
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom N: charge=-1, no H, has no double bond, endpoint */
                 num_SB_N_Minus < MAX_DIFF_FIXH &&
                 at2[iat].charge == -1 && /*!at2[iat].num_H &&*/
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1 &&
                 at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint &&
                 /* in orig.InChI: may be an endpoint, has no H */
                 /* has (-) edge */
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                iat_SB_N_Minus[num_SB_N_Minus ++] = iat;
            } else
            if ( num_DB_O < MAX_DIFF_FIXH &&
                 at2[iat].charge == 0 && /*!at2[iat].num_H &&*/
                 at2[iat].valence+1 == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 6 &&
                 at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint && /* endpoint in Reconstructed */
                 (pStruct->endpoint[i] || /* endpoint or H(+) acceptor in original */
                  (pnMobHInChI && pnMobHInChI[i] == 1 && pnFixHInChI && pnFixHInChI[i] == -1) ) &&
                 /* has (-) edge */
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                iat_DB_O[num_DB_O ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }    
        }
        if ( (num_try = inchi_min( num_SB_N_Minus, num_DB_O )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            /* allow charge transfer to all found =O */
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_N_Minus && cur_success < num_try; i ++ ) {
                iat = iat_SB_N_Minus[i];
                pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Added (-) charge to =O => nDeltaCharge == 1 */
                    /* Flow change on pe (-)charge edge (atom -N(-)-) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 03a */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at >= 1 && pc2i->nNumTgInChI == 1 && /* ADP in InChI */
         (pc2i->nNumEndpRevrs < pc2i->nNumEndpInChI || pc2i->nNumTgRevrs > 1) ) {
        /*--------------------------------------------------------------*/
        /* case 04: restored: OH(+)=AB-O- OH- orig.  HO-AB=O(+)- OH-    */
        /* FixH:               1       0   0          1      0   1      */
        /* MobH:               0       0   1          0      0   0      */
        /*                 non-taut.                taut        taut    */
        /*                                    ADP: one t-group or more endpoints */
        /* O(+) = N, P, As, As, O, S, Se; OH = N, O, S, Se, Te          */
        /* Solution: move (+) from O(+) to NH2                          */
        /*--------------------------------------------------------------*/
        int num_SB_Neutr = 0, num_DB_Charged = 0, iat;
        short iat_SB_Neutr[MAX_DIFF_FIXH], iat_DB_Charged[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom: charge=+1, has H, has double bond, N, O, S, Se, Te */
                 num_DB_Charged < MAX_DIFF_FIXH &&
                 at2[iat].charge == 1 && at2[iat].num_H &&
                 at2[iat].valence < at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 (pVA[iat].cNumValenceElectrons == 6 ||
                  (pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1)) &&
                 /* in orig.InChI: an endpoint, has fixed-H */
                 pStruct->endpoint[i] && 
                 (pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 /*!(nMobHInChI && nMobHInChI[i] ) &&*/
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {

                iat_DB_Charged[num_DB_Charged ++] = iat;
                
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            } else
            if ( /* in restored atom: charge=0, has no H, has no double bond, N, P, O, S, Se, Te */
                 num_SB_Neutr < MAX_DIFF_FIXH &&
                 at2[iat].charge == 0 && !at2[iat].num_H &&
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 (pVA[iat].cNumValenceElectrons == 6 ||
                  pVA[iat].cNumValenceElectrons == 5 ) &&
                 /* in orig.InChI: an endpoint, has fixed-H */
                 /* pStruct->endpoint[i] && */
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 &&
                 0 == pBNS->edge[e].forbidden ) {

                iat_SB_Neutr[num_SB_Neutr ++] = iat;
                
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_Neutr, num_DB_Charged )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_Neutr && cur_success < num_try; i ++ ) {
                iat = iat_SB_Neutr[i];
                pe   = pBNS->edge + pVA[iat].nCPlusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == -1 ) {
                    /* Removed charge from O(+) => nDeltaCharge == -1 */
                    /* Flow change on pe (+)charge edge (atom NH2) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 04 */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at > 1 ) {
        /*--------------------------------------------------------------*/
        /* case 05: restored:  O=AB-NH      original:(-)O-AB=NH(+)      */
        /* FixH:               0     0                 -1     1         */
        /* MobH:               0     1                  1     0         */
        /* O = O, S, Se; N = N, O, S, Se, Te; all atoms not tautomeric  */
        /* Solution: Separate charges                                   */
        /*--------------------------------------------------------------*/
        int num_DB_O = 0, num_SB_NH = 0, iat;
        short iat_DB_O[MAX_DIFF_FIXH], iat_SB_NH[MAX_DIFF_FIXH];
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: =NH2(+), =OH(+) */
                 num_SB_NH < MAX_DIFF_FIXH &&
                 ((pc2i->c2at[i].nValElectr == 5 && pc2i->c2at[i].nPeriodNum == 1) ||
                  pc2i->c2at[i].nValElectr == 6 ) /* N, O, S, Se, Te */ &&
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == 1 && /*pc2i->c2at[i].nMobHInChI ==  1 &&*/
                 /* reversed structure info: */
                 pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && at2[iat].num_H &&
                 !pc2i->c2at[i].endptRevrs &&
                 at2[iat].valence == at2[iat].chem_bonds_valence ) {
                iat_SB_NH[num_SB_NH ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            } else
            if ( /* orig. InChI info: -O(-) */
                 num_DB_O < MAX_DIFF_FIXH &&
                 (pc2i->c2at[i].nValElectr == 6 ) /* O, S, Se, Te */ &&
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == -1 && pc2i->c2at[i].nMobHInChI ==  1 &&
                 /* reversed structure info: */
                 pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs == 0 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 !pc2i->c2at[i].endptRevrs &&
                 at2[iat].valence + 1 == at2[iat].chem_bonds_valence ) {
                iat_DB_O[num_DB_O ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_DB_O, num_SB_NH )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_NH && cur_success < num_try; i ++ ) {
                iat = iat_SB_NH[i];
                pe   = pBNS->edge + pVA[iat].nCPlusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Added charge to =O => nDeltaCharge == 1 */
                    /* Flow change on pe (+)charge edge (atom NH2) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 05 */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pStruct->fixed_H && pStruct->endpoint && pc2i->nChargeFixHInChI > 0 && pc2i->nChargeFixHInChI > pc2i->nChargeMobHInChI ) {
        /*----------------------------------------------------------*/
        /* case 06c: restored -NH- or -NH(+)  orig: -NH-            */
        /*  Fixed-H            1       1             0              */
        /*  Mobile-H           0       0             1              */
        /*                     not tautomeric    not tautomeric     */
        /*           has adjacent (+)                               */
        /*           charges                                        */
        /*  Solution: move (+) charges to the -NH- unless it already*/
        /*            N = N, O, S, Se, Te                           */
        /*            has (+) charge blocked by adjacent (+)        */
        /*----------------------------------------------------------*/
        int iat;
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        /*
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        inp_ATOM *atfMobile_H_Revrs = pStruct->pOne_norm_data[TAUT_YES] &&
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds?
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds : NULL;
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : NULL;
        */
        EDGE_LIST CurChargeEdges;
        EdgeIndex e2;
        cur_success = 0;
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_CLEAR );
        CurrEdges.num_edges = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            /* atoms -NH- from which H(+) were removed by the Normalization in orig. InChI */
            iat = pc2i->c2at[i].atomNumber;
            if ( (pc2i->c2at[i].nValElectr == 6 ||
                  (pc2i->c2at[i].nValElectr == 5 && pc2i->c2at[i].nPeriodNum == 1)) &&
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                if ( /* orig. InChI info: -NH- */
                     pc2i->c2at[i].nFixHInChI == 1 && pc2i->c2at[i].nMobHInChI == 0 &&
                     /* reversed structure info: */
                     pc2i->c2at[i].nFixHRevrs == 0 && pc2i->c2at[i].nMobHRevrs == 1 && /* was not removed */
                     /*pc2i->c2at[i].nAtChargeRevrs == 0 &&*/ at2[iat].num_H && /* at2 is Fixed-H */
                     at2[iat].valence == at2[iat].chem_bonds_valence ) {
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                }
            }
        }
        for ( i = 0; i < pStruct->num_atoms; i ++ ) {
            /* find adjacent charged atoms */
            iat = nCanon2AtnoRevrs[i];
            if ( pStruct->endpoint[i] || at2[iat].charge != 1 || at2[iat].radical || pVA[iat].cMetal ) {
                continue;
            }
            if ( 0 <= (e=pVA[iat].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden && !pBNS->edge[e].flow && pVA[iat].cNumValenceElectrons >= 5 ) {
                /* positively charged atom */
                for ( j = 0; j < at2[iat].valence; j ++ ) {
                    if ( at2[k=(int)at2[iat].neighbor[j]].charge == 1 && !pVA[k].cMetal &&
                         0 <= (e2=pVA[k].nCPlusGroupEdge-1) && !pBNS->edge[e2].forbidden && !pBNS->edge[e2].flow) {
                        if ( 0 > FindInEdgeList( &CurrEdges, e ) &&
                             0 > FindInEdgeList( &CurChargeEdges, e ) &&
                             ( ret = AddToEdgeList( &CurChargeEdges, e, INC_ADD_EDGE ) ) ) {
                            goto exit_case_06c;
                        }
                        if ( 0 > FindInEdgeList( &CurrEdges, e2 ) &&
                             0 > FindInEdgeList( &CurChargeEdges, e2 ) &&
                             ( ret = AddToEdgeList( &CurChargeEdges, e2, INC_ADD_EDGE ) ) ) {
                            goto exit_case_06c;
                        }
                    }
                }
            }
        }
        if ( (num_try = inchi_min( CurrEdges.num_edges, CurChargeEdges.num_edges )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurChargeEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < CurrEdges.num_edges && cur_success < num_try; i ++ ) {
                e = CurrEdges.pnEdges[i];
                pe   = pBNS->edge + e; /* (+)charge edge of -NH- or -OH */
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->flow -= delta; /* add (+) to -NHm */
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == -1 ) {
                    /* Removed (+)charge from -NH- => nDeltaCharge == -1 */
                    /* Flow change on pe (+)charge edge (atom NHm(+)) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 06c */
                    }
                } else {
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
exit_case_06c:
        CurrEdges.num_edges = 0; /* clear current edge list */
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_FREE );
        if ( ret < 0 ) {
            goto exit_function;
        }
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at >= 2 ) {
        /*------------------------------------------------------------*/
        /* case 06d: restored: XH(+)=-AB-NH    orig.: XH-=AB=NH(+)    */
        /* FixH:                1       1 0          0 1      1       */
        /* MobH:                0    taut 1          1 taut   0       */
        /*                                                            */
        /*                                                            */
        /* N  = N, O, S, Se; atoms N are not tautomeric in orig InChI */
        /* X  = N, O, S, Se, Te, F, Cl, Br, I; atom X is non-taut     */
        /* Solution: move (+) from X  to NH                           */
        /*------------------------------------------------------------*/
        int iat;
        /*
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        inp_ATOM *atfMobile_H_Revrs = pStruct->pOne_norm_data[TAUT_YES] &&
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds?
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds : 
                                      pStruct->pOne_norm_data[TAUT_NON]->at;
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        EDGE_LIST CurChargeEdges;
        cur_success = 0;
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_CLEAR );
        CurrEdges.num_edges = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            /* XH(+) */
            if ( /* reconstructed: non-taut and (+) */
                 (pc2i->c2at[i].nMobHRevrs+1 == pc2i->c2at[i].nFixHRevrs &&
                 pc2i->c2at[i].nFixHRevrs > 0 && !pc2i->c2at[i].endptRevrs &&
                 pc2i->c2at[i].nAtChargeRevrs == 1 &&
                 /* original InChI: non-taut & has H or an endpoint, has Fixed H */
                 ((!pc2i->c2at[i].nFixHInChI && pc2i->c2at[i].nMobHInChI == pc2i->c2at[i].nFixHRevrs) ||
                 (pc2i->c2at[i].nFixHInChI == pc2i->c2at[i].nFixHRevrs && pc2i->c2at[i].endptInChI) ))  &&
                 0 <= (e=pVA[iat].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden && !pBNS->edge[e].flow) {

                if ( (ret = AddToEdgeList( &CurChargeEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_case_06d;
                }
            } else
            /* -NH- */
            if ( /* original InChI: has H and is not an endpoint */
                (pc2i->c2at[i].nMobHInChI+1 == pc2i->c2at[i].nFixHInChI && 
                 pc2i->c2at[i].nFixHInChI > 0 && !pc2i->c2at[i].endptInChI &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 &&
                 /* reconstructed InChI: non-taut & has H or an endpoint, has Fixed H */
                 ((!pc2i->c2at[i].nFixHRevrs && pc2i->c2at[i].nMobHRevrs == pc2i->c2at[i].nFixHInChI) ||
                 (pc2i->c2at[i].nFixHRevrs == pc2i->c2at[i].nFixHInChI && pc2i->c2at[i].endptRevrs) ))  &&
                 0 <= (e=pVA[iat].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden && 
                 pBNS->edge[e].flow) {

                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_case_06d;
                }
            }
        }
        if ( (num_try = inchi_min( CurrEdges.num_edges, CurChargeEdges.num_edges )) ) {
            /* detected; attempt to fix */
            int bSFlowerEdgesMayBeForbidden = (SFlowerEdges.num_edges > 0);
            int bSFlowerEdgesIsForbidden;
            for ( bSFlowerEdgesIsForbidden = bSFlowerEdgesMayBeForbidden;
                     0 <= bSFlowerEdgesIsForbidden; bSFlowerEdgesIsForbidden -- ) {
                if ( bSFlowerEdgesIsForbidden ) {
                    /* on the 1st pass disallow -S(+)= => =S=, allow only -S(+)= => -S- */
                    SetForbiddenEdgeMask( pBNS, &SFlowerEdges, forbidden_edge_mask );
                }
                SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                RemoveForbiddenEdgeMask( pBNS, &CurChargeEdges, forbidden_edge_mask  );
                delta = 1;
                for ( i = 0; i < CurrEdges.num_edges && cur_success < num_try; i ++ ) {
                    e = CurrEdges.pnEdges[i];
                    pe   = pBNS->edge + e; /* (+)charge edge of -NH- or -OH */
                    if ( !pe->flow )
                        continue;
                    pv1 = pBNS->vert + (v1 = pe->neighbor1);
                    pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                    pe->flow -= delta; /* add (+) to -NHm */
                    pv1->st_edge.flow -= delta;
                    pv2->st_edge.flow -= delta;
                    pBNS->tot_st_flow -= 2*delta;

                    ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                          &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                    if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                      (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == -1 ) {
                        /* Removed (+)charge from -NH- => nDeltaCharge == -1 */
                        /* Flow change on pe (+)charge edge (atom NHm(+)) is not known to RunBnsTestOnce()) */
                        ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                        if ( ret > 0 ) {
                            nNumRunBNS ++;
                            cur_success ++; /* 06d */
                        }
                    } else {
                        pe->flow += delta;
                        pv1->st_edge.flow += delta;
                        pv2->st_edge.flow += delta;
                        pBNS->tot_st_flow += 2*delta;
                    }
                    INCHI_HEAPCHK
                }
                RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
                RemoveForbiddenEdgeMask( pBNS, &SFlowerEdges, forbidden_edge_mask );
            }

        }
exit_case_06d:
        CurrEdges.num_edges = 0; /* clear current edge list */
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_FREE );
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }


    if ( pc2i->len_c2at >= 2 ) {
        /*--------------------------------------------------------*/
        /* case 06: restored: NHn(+)=AB-NHm  orig.: NHn-AB=NHm(+) */
        /* FixH:               1        0            0     1      */
        /* MobH:              n-1       m            n    m-1     */
        /* N = N, O, S, Se; atoms N are not tautomeric            */
        /* Solution: move (+) from NHn(+) to NHn                  */
        /*--------------------------------------------------------*/
        int num_DB_NHn_Plus = 0, num_SB_NHm_Neutr = 0, iat;
        short iat_DB_NHn_Plus[MAX_DIFF_FIXH], iat_SB_NHm_Neutr[MAX_DIFF_FIXH];
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( (pc2i->c2at[i].nValElectr == 6 ||
                  (pc2i->c2at[i].nValElectr == 5 && pc2i->c2at[i].nPeriodNum == 1)) &&
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                if ( /* orig. InChI info: NHm */
                     num_SB_NHm_Neutr < MAX_DIFF_FIXH &&
                     pc2i->c2at[i].nFixHInChI == 1 && /*pc2i->c2at[i].nMobHInChI == 0 &&*/
                     /* reversed structure info: */
                     pc2i->c2at[i].nFixHRevrs == 0 && /*pc2i->c2at[i].nMobHRevrs == 1 &&*/
                     pc2i->c2at[i].nAtChargeRevrs == 0 && at2[iat].num_H && /* at2 is Fixed-H */
                     at2[iat].valence == at2[iat].chem_bonds_valence ) {
                    iat_SB_NHm_Neutr[num_SB_NHm_Neutr ++] = iat;
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                } else
                if ( /* orig. InChI info: */
                     num_DB_NHn_Plus < MAX_DIFF_FIXH &&
                     pc2i->c2at[i].nFixHInChI == 0 && /*pc2i->c2at[i].nMobHInChI &&*/
                     /* reversed structure info: */
                     pc2i->c2at[i].nFixHRevrs ==  1 && /*pc2i->c2at[i].nMobHRevrs ==  0 &&*/
                     pc2i->c2at[i].nAtChargeRevrs == 1 && at2[iat].num_H &&
                     at2[iat].valence < at2[iat].chem_bonds_valence ) {
                    iat_DB_NHn_Plus[num_DB_NHn_Plus ++] = iat;
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_NHm_Neutr, num_DB_NHn_Plus )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_NHm_Neutr && cur_success < num_try; i ++ ) {
                iat = iat_SB_NHm_Neutr[i];
                pe   = pBNS->edge + pVA[iat].nCPlusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta; /* add (+) to -NHm */
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == -1 ) {
                    /* Removed (+)charge from -NHn => nDeltaCharge == -1 */
                    /* Flow change on pe (+)charge edge (atom NHm(+)) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 06 */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( ((pc2i->nNumTgInChI > pc2i->nNumTgRevrs && pc2i->nNumTgRevrs == 1) ||
          pc2i->nNumEndpInChI < pc2i->nNumEndpRevrs ) &&
          pStruct->nNumRemovedProtonsMobHInChI == pStruct->One_ti.tni.nNumRemovedProtons &&
          pStruct->fixed_H && pStruct->endpoint && pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds ) {
        /*----------------------------------------------------------*/
        /* case 06a: restored: N'(+)=-AB-NH    orig.: N'-=AB=NH(+)  */
        /* FixH:               0         1            0      1      */
        /* MobH:               0         0            0      0      */
        /*                    single t-group      multiple t-groups */
        /* N  = N, O, S, Se; atoms N are not tautomeric             */
        /* N' = N            atom N' is not tautomeric              */
        /* Solution: move (+) from N' to NH                         */
        /*----------------------------------------------------------*/
        int iat;
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        /*
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        */
        inp_ATOM *atfMobile_H_Revrs = pStruct->pOne_norm_data[TAUT_YES] &&
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds?
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds : NULL;
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        EDGE_LIST CurChargeEdges;
        cur_success = 0;
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_CLEAR );
        CurrEdges.num_edges = 0;
        for ( i = 0; i < pStruct->num_atoms; i ++ ) {
            iat = nCanon2AtnoRevrs[i];
            if ( pStruct->endpoint[i] ) {
                continue;
            }
            /* -NH-, -OH */
            if ( pStruct->fixed_H[i] && !nMobHInChI[i] &&
                 at2[iat].charge == 0 && at2[iat].radical == 0 &&
                 0 <= (e=pVA[iat].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden && pBNS->edge[e].flow &&
                 (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE ))) {
                goto exit_case_06a;
            } else
            /* >N(+)= */
            if ( at2[iat].charge == 1 && !at2[iat].num_H &&
                 pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1 &&
                 atfMobile_H_Revrs && atfMobile_H_Revrs[iat].charge == 0 &&
                 0 <= (e=pVA[iat].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden && !pBNS->edge[e].flow &&
                 (ret = AddToEdgeList( &CurChargeEdges, e, INC_ADD_EDGE ))) {
                goto exit_case_06a;
            }
        }
        if ( (num_try = inchi_min( CurrEdges.num_edges, CurChargeEdges.num_edges )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurChargeEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < CurrEdges.num_edges && cur_success < num_try; i ++ ) {
                e = CurrEdges.pnEdges[i];
                pe   = pBNS->edge + e; /* (+)charge edge of -NH- or -OH */
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->flow -= delta; /* add (+) to -NHm */
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == -1 ) {
                    /* Removed (+)charge from -NH- => nDeltaCharge == -1 */
                    /* Flow change on pe (+)charge edge (atom NHm(+)) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 06a */
                    }
                } else {
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
exit_case_06a:
        CurrEdges.num_edges = 0; /* clear current edge list */
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_FREE );
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }
    if ( ((pc2i->nNumTgInChI > pc2i->nNumTgRevrs && pc2i->nNumTgRevrs == 1) ||
          pc2i->nNumEndpInChI < pc2i->nNumEndpRevrs ) &&
          (pStruct->nNumRemovedProtonsMobHInChI == pStruct->One_ti.tni.nNumRemovedProtons ||
           pStruct->nNumRemovedProtonsMobHInChI > pStruct->One_ti.tni.nNumRemovedProtons ) &&
          pStruct->fixed_H && pStruct->endpoint && pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds ) {
        /*----------------------------------------------------------*/
        /* case 06b: restored: X(+)=-AB-NH    orig.: X-=AB=NH(+)    */
        /* FixH:               0        1 1          0      1       */
        /* MobH:               0        0 t          0      0       */
        /*                    single t-group      multiple t-groups */
        /*                                        or no t-groupd    */
        /* N  = N, O, S, Se; atoms N are not tautomeric             */
        /* X  = O, S, Se, Te, F, Cl, Br, I; atom X is not tautomeric*/
        /* Solution: move (+) from X  to NH                         */
        /*----------------------------------------------------------*/
        int iat;
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        /*
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        */
        inp_ATOM *atfMobile_H_Revrs = pStruct->pOne_norm_data[TAUT_YES] &&
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds?
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds : NULL;
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        EDGE_LIST CurChargeEdges;
        cur_success = 0;
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_CLEAR );
        CurrEdges.num_edges = 0;
        for ( i = 0; i < pStruct->num_atoms; i ++ ) {
            iat = nCanon2AtnoRevrs[i];
            if ( pStruct->endpoint[i] ) {
                continue;
            }
            /* -NH-, -OH */
            if ( pStruct->fixed_H[i] && !nMobHInChI[i] &&
                 at2[iat].charge == 0 && at2[iat].radical == 0 &&
                 0 <= (e=pVA[iat].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden && pBNS->edge[e].flow &&
                 (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE ))) {
                goto exit_case_06b;
            } else
            /* X(+)= */
            if ( at2[iat].charge == 1 && !at2[iat].num_H &&
                 (pVA[iat].cNumValenceElectrons == 6 || pVA[iat].cPeriodicRowNumber == 7) &&
                 atfMobile_H_Revrs && atfMobile_H_Revrs[iat].charge == 1 &&
                 0 <= (e=pVA[iat].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden && !pBNS->edge[e].flow &&
                 (ret = AddToEdgeList( &CurChargeEdges, e, INC_ADD_EDGE ))) {
                goto exit_case_06b;
            }
        }
        if ( (num_try = inchi_min( CurrEdges.num_edges, CurChargeEdges.num_edges )) ) {
            /* detected; attempt to fix */
            int bSFlowerEdgesMayBeForbidden = (SFlowerEdges.num_edges > 0);
            int bSFlowerEdgesIsForbidden;
            for ( bSFlowerEdgesIsForbidden = bSFlowerEdgesMayBeForbidden;
                     0 <= bSFlowerEdgesIsForbidden; bSFlowerEdgesIsForbidden -- ) {
                if ( bSFlowerEdgesIsForbidden ) {
                    /* on the 1st pass disallow -S(+)= => =S=, allow only -S(+)= => -S- */
                    SetForbiddenEdgeMask( pBNS, &SFlowerEdges, forbidden_edge_mask );
                }
                SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                RemoveForbiddenEdgeMask( pBNS, &CurChargeEdges, forbidden_edge_mask  );
                delta = 1;
                for ( i = 0; i < CurrEdges.num_edges && cur_success < num_try; i ++ ) {
                    e = CurrEdges.pnEdges[i];
                    pe   = pBNS->edge + e; /* (+)charge edge of -NH- or -OH */
                    if ( !pe->flow )
                        continue;
                    pv1 = pBNS->vert + (v1 = pe->neighbor1);
                    pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                    pe->flow -= delta; /* add (+) to -NHm */
                    pv1->st_edge.flow -= delta;
                    pv2->st_edge.flow -= delta;
                    pBNS->tot_st_flow -= 2*delta;

                    ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                          &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                    if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                      (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == -1 ) {
                        /* Removed (+)charge from -NH- => nDeltaCharge == -1 */
                        /* Flow change on pe (+)charge edge (atom NHm(+)) is not known to RunBnsTestOnce()) */
                        ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                        if ( ret > 0 ) {
                            nNumRunBNS ++;
                            cur_success ++; /* 06b */
                        }
                    } else {
                        pe->flow += delta;
                        pv1->st_edge.flow += delta;
                        pv2->st_edge.flow += delta;
                        pBNS->tot_st_flow += 2*delta;
                    }
                    INCHI_HEAPCHK
                }
                RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
                RemoveForbiddenEdgeMask( pBNS, &SFlowerEdges, forbidden_edge_mask );
            }

        }
exit_case_06b:
        CurrEdges.num_edges = 0; /* clear current edge list */
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_FREE );
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }



    if ( pc2i->nNumTgInChI > 1 &&
          (pStruct->nNumRemovedProtonsMobHInChI > 0 || pStruct->ti.tni.nNumRemovedProtons > 0 ) &&
          pStruct->fixed_H && pStruct->endpoint && 
          pStruct->pOne_norm_data[TAUT_YES] && pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds ) {
        /*----------------------------------------------------------*/
        /* case 06e:restored: XHn(+)=-AB-YHm  orig.: XHn-=AB=YHm(+) */
        /* FixH:               1          0           1      1      */
        /* MobH:               0          1           t      t      */
        /*                   non-taut atoms       multiple t-groups */
        /*                                                          */
        /* 1. orig. t-group has more H on its endpoints counted     */
        /*          in atf and has no (+) on endpoint that has H    */
        /* 2. orig. t-group has less H on its endpoints counted     */
        /*          in atf and has (+) on endpoint that has H       */
        /*          in reconstructed struct and less H in atf       */
        /* Solution: move (+) from (2) to atom in (1) that has H    */
        /*                                                          */
        /*   tg1  reconstr:   XHn and more H than in orig t-group   */
        /*             atf:   XHn                                   */
        /*   tg2  reconstr:   XHm(+) and less H than in             */
        /*             atf:   XH(m-1)           orig in t-group     */
        /*                                                          */
        /* N  = N, O, S, Se; atoms N are not tautomeric             */
        /* X  = O, S, Se, Te, F, Cl, Br, I; atom X is not tautomeric*/
        /* Solution: move (+) from X  to NH                         */
        /*----------------------------------------------------------*/

        int iat, nNumWrongTg, jjoffs, jj, nNum2RemovePlus, nNum2AddPlus, nNum2MovePlus;
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        /*
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        */
        inp_ATOM *atfMobile_H_Revrs = pStruct->pOne_norm_data[TAUT_YES] &&
                                      pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds?
                                            pStruct->pOne_norm_data[TAUT_YES]->at_fixed_bonds :
                                      pStruct->pOne_norm_data[TAUT_YES] &&
                                      pStruct->pOne_norm_data[TAUT_YES]->at?
                                            pStruct->pOne_norm_data[TAUT_YES]->at : NULL;
        /*
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        EDGE_LIST CurChargeEdges /* source of (+)*/, EndpList;
        TgDiffHChgFH tdhc[MAX_DIFF_FIXH];
        BNS_VERTEX *pv1n, *pv2n;
        BNS_EDGE   *pe1n, *pe2n;
        Vertex      v1n, v2n;

        cur_success = 0;
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_CLEAR );
        AllocEdgeList( &EndpList, EDGE_LIST_CLEAR );
        CurrEdges.num_edges = 0; /* receptors of (+) */
        if ( !atfMobile_H_Revrs ) {
            goto exit_case_06e;
        }
        nNumWrongTg = FillTgDiffHChgFH( tdhc, MAX_DIFF_FIXH, at2, atfMobile_H_Revrs,
                                       nCanon2AtnoRevrs, pVA, &pStruct->ti, &EndpList );
        if ( nNumWrongTg < 1 ) {
            goto exit_case_06e; /* for now only transfer (+) from one Mobile-H group to another */
        }
        nNum2RemovePlus = nNum2AddPlus = nNum2MovePlus = 0;
        for ( i = 0; i < nNumWrongTg; i ++ ) {
            /* detect t-group that has extra (+) on H */
            if ( tdhc[i].nNumHInchi > tdhc[i].nNumHNorml &&
                 tdhc[i].nNumPRevrs > tdhc[i].nNumPNorml && tdhc[i].n[fNumRPosChgH] ) {
                /* count how many (+) to remove */
                /* store XH(+) atom numbers */
                int nNumNeeded = inchi_min( tdhc[i].nNumHInchi-tdhc[i].nNumHNorml, tdhc[i].n[fNumRPosChgH]);
                nNum2RemovePlus += nNumNeeded;
                jjoffs = tdhc[i].i[ fNumRPosChgH ];
                for ( jj = 0; jj < tdhc[i].n[fNumRPosChgH]; jj ++ ) {
                    iat = EndpList.pnEdges[ jjoffs + jj ];
                    e = pVA[iat].nCPlusGroupEdge-1;
                    if ( (ret = AddToEdgeList( &CurChargeEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_case_06e;
                    }
                }
            } else
            /* detect t-group that needs (+) on XH to reduce number of H */
            if ( tdhc[i].nNumHInchi < tdhc[i].nNumHNorml && tdhc[i].n[fNumRNeutrlH] ) {
                /* store XH atom numbers */
                int nNumNeeded = inchi_min( tdhc[i].nNumHNorml-tdhc[i].nNumHInchi, tdhc[i].n[fNumRNeutrlH]);
                nNum2AddPlus += nNumNeeded;
                jjoffs = tdhc[i].i[ fNumRNeutrlH ];
                for ( jj = 0; jj < tdhc[i].n[fNumRNeutrlH]; jj ++ ) {
                    iat = EndpList.pnEdges[ jjoffs + jj ];
                    e = pVA[iat].nCPlusGroupEdge-1;
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_case_06e;
                    }
                }
            }
        }
        nNum2MovePlus = inchi_min( nNum2RemovePlus, nNum2AddPlus );
        if ( CurrEdges.num_edges > 0 && CurChargeEdges.num_edges > 0 ) {
            for ( i = 0; 0 < nNum2MovePlus && i < nNumWrongTg; i ++ ) {
                /* detect t-group that has extra (+) on H */
                if ( tdhc[i].nNumHInchi > tdhc[i].nNumHNorml &&
                     tdhc[i].nNumPRevrs > tdhc[i].nNumPNorml && tdhc[i].n[fNumRPosChgH] ) {
                    int nNum2Remove = tdhc[i].nNumHInchi - tdhc[i].nNumHNorml;
                    if ( nNum2Remove < tdhc[i].n[fNumRPosChgH] ) {
                        nNum2Remove = tdhc[i].n[fNumRPosChgH];
                    }
                    /* store XH(+) atom numbers */
                    jjoffs = tdhc[i].i[ fNumRPosChgH ];
                    SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
                    RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
                    for ( jj = 0; 0 < nNum2MovePlus && 0 < nNum2Remove && jj < tdhc[i].n[fNumRPosChgH]; jj ++ ) {
                        iat = EndpList.pnEdges[ jjoffs + jj ];
                        e = pVA[iat].nCPlusGroupEdge-1;
                        pe   = pBNS->edge + pVA[iat].nCPlusGroupEdge-1;
                        if ( pe->flow )
                            continue;
                        pv1 = pBNS->vert + (v1 = pe->neighbor1);
                        pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                        for ( j = pv1->num_adj_edges-1; 0 <= j; j -- ) {
                            pe1n = pBNS->edge + pv1->iedge[j];
                            if ( pe1n->flow && !pe1n->forbidden ) {
                                pv1n = pBNS->vert + (v1n = pe1n->neighbor12 ^ v1);
                                break;
                            }
                        }
                        if ( j < 0 )
                            continue; /* not found */
                        
                        for ( j = pv2->num_adj_edges-2; 0 <= j; j -- ) {
                            pe2n = pBNS->edge + pv2->iedge[j];
                            if ( pe2n->flow && !pe2n->forbidden ) {
                                pv2n = pBNS->vert + (v2n = pe2n->neighbor12 ^ v2);
                                break;
                            }
                        }
                        if ( j < 0 )
                            continue; /* not found */
                        delta = 1;
                        pe->flow   += delta;
                        pe1n->flow -= delta;
                        pe2n->flow -= delta;
                        pv1n->st_edge.flow -= delta;
                        pv2n->st_edge.flow -= delta;
                        pBNS->tot_st_flow -= 2*delta;

                        ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                              &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                        if ( ret == 1 && ((vPathEnd == v1n && vPathStart == v2n) ||
                                          (vPathEnd == v2n && vPathStart == v1n)) &&
                                          (nDeltaCharge == 0 || nDeltaCharge == 1) ) {
                            ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                            if ( ret > 0 ) {
                                nNumRunBNS ++;
                                nNum2Remove --;
                                nNum2MovePlus --;
                                cur_success ++; /* 06e */
                            }
                        } else {
                            pe->flow   -= delta;
                            pe1n->flow += delta;
                            pe2n->flow += delta;
                            pv1n->st_edge.flow += delta;
                            pv2n->st_edge.flow += delta;
                            pBNS->tot_st_flow += 2*delta;
                        }
                        if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                            goto exit_case_06e;
                        }
                    }
                    RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
                }
            }
        }
exit_case_06e:
        CurrEdges.num_edges = 0; /* clear current edge list */
        AllocEdgeList( &CurChargeEdges, EDGE_LIST_FREE );
        AllocEdgeList( &EndpList, EDGE_LIST_FREE );
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }



    if ( pc2i->len_c2at >= 1 ) {
        /*--------------------------------------------------------------*/
        /* case 07: restored:  O(-)-AB=O  original:  O=AB-O(-)          */
        /* FixH:               0       0             0     -1           */
        /* MobH:               0       0             0      1           */
        /*                    taut  (non-taut)     (taut) non-taut      */
        /*                    taut  (taut)     (non-taut) non-taut      */   
        /* O = O, S, Se, Te                                             */
        /* Solution: move (-) from O(-)-AB to AB=O                      */
        /*--------------------------------------------------------------*/
        int num_SB_O_Minus = 0, num_DB_O_Neutr = 0, iat;
        short iat_SB_O_Minus[MAX_DIFF_FIXH], iat_DB_O_Neutr[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: -O(-), non-taut */
                 num_DB_O_Neutr < MAX_DIFF_FIXH &&
                 pc2i->c2at[i].nValElectr == 6 /* O, S, Se, Te */ &&
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == -1 && pc2i->c2at[i].nMobHInChI ==  1 &&
                 /* reversed structure info: */
                 pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs == 0 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 at2[iat].valence < at2[iat].chem_bonds_valence ) {
                iat_DB_O_Neutr[num_DB_O_Neutr ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom: charge=-1, no H, has single bond, O, S, Se, Te */
                 num_SB_O_Minus < MAX_DIFF_FIXH &&
                 at2[iat].charge == -1 && !at2[iat].num_H &&
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 6 &&
                 at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint &&
                 /* in orig.InChI: not an endpoint, has no H */
                 /*pStruct->endpoint[i] && -- modificatuion#1 */
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (-) edge */
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                iat_SB_O_Minus[num_SB_O_Minus ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_O_Minus, num_DB_O_Neutr )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_O_Minus && cur_success < num_try; i ++ ) {
                iat = iat_SB_O_Minus[i];
                pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Moved (-) charge to AB=O => nDeltaCharge == 1 */
                    /* Flow change on pe (-)charge edge (O(-)-AB) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 07 */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at >= 1 ) {
        /*--------------------------------------------------------------*/
        /* case 07a: restored: O(-)-N(V)B=O  original:  O=N(V)B-O(-)    */
        /* FixH:               0          0             0      -1       */
        /* MobH:               0          0             0       1       */
        /*                non-taut  (non-taut)  non-taut  non-taut      */
        /*                non-taut  (taut)      non-taut  non-taut      */   
        /* O = O, S, Se, Te                                             */
        /* Solution: move (-) from O(-)-AB to AB=O                      */
        /*--------------------------------------------------------------*/
        int num_SB_O_Minus = 0, num_DB_O_Neutr = 0, iat, iN;
        short iat_SB_O_Minus[MAX_DIFF_FIXH], iat_DB_O_Neutr[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: -O(-), non-taut */
                 num_DB_O_Neutr < MAX_DIFF_FIXH &&
                 pc2i->c2at[i].nValElectr == 6 /* O, S, Se, Te */ &&
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == -1 && pc2i->c2at[i].nMobHInChI ==  1 &&
                 /* reversed structure info: */
                 pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs == 0 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 at2[iat].valence < at2[iat].chem_bonds_valence ) {
                iat_DB_O_Neutr[num_DB_O_Neutr ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom: charge=-1, no H, has single bond, O, S, Se, Te */
                 num_SB_O_Minus < MAX_DIFF_FIXH &&
                 at2[iat].charge == -1 && !at2[iat].num_H &&
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 6 &&
                 /*at_Mobile_H_Revrs && !at_Mobile_H_Revrs[iat].endpoint &&*/
                 /* in orig.InChI: not an endpoint, has no H */
                 !pStruct->endpoint[i] &&
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has N(V) neighbor */
                 1 == at2[iat].valence && at2[iN=at2[iat].neighbor[0]].chem_bonds_valence==5 &&
                 !at2[iN].charge && pVA[iN].cNumValenceElectrons == 5 &&
                 /* has (-) edge */
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                iat_SB_O_Minus[num_SB_O_Minus ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_O_Minus, num_DB_O_Neutr )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_O_Minus && cur_success < num_try; i ++ ) {
                iat = iat_SB_O_Minus[i];
                pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Moved (-) charge to AB=O => nDeltaCharge == 1 */
                    /* Flow change on pe (-)charge edge (O(-)-AB) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 07 */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }
    if ( /*(pc2i->len_c2at >= 1 || pc2i->nNumRemHRevrs) &&*/ pc2i->nNumTgInChI == 1 && /* ADP in InChI */
         (pc2i->nNumEndpRevrs < pc2i->nNumEndpInChI || pc2i->nNumTgRevrs > 1) ) {
        /*----------------------------------------------------------------*/
        /* case 08: restored: O(-)-AB=N- OH- orig.   O=AB-N(-)- OH-       */
        /* FixH:               1      0   0          0      0   1         */
        /* MobH:               0      0   1          0      0   0         */
        /*           may be taut or not  non-taut   taut  taut taut       */
        /*                                    ADP: one t-group or more endpoints */
        /* O(-) = S, Se, Te; N = N;                                       */
        /* Solution: move (-) from O(-) to =N-; avoid stereogenic DB on N */
        /*----------------------------------------------------------------*/
        int num_DB_N_Neutr = 0, num_SB_O_Minus = 0, iat;
        short iat_DB_N_Neutr[MAX_DIFF_FIXH], iat_SB_O_Minus[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom: charge=-1, has no H, has single bond, O, S, Se, Te */
                 num_SB_O_Minus < MAX_DIFF_FIXH &&
                 at2[iat].charge == -1 && !at2[iat].num_H &&
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 6 &&
                 /* in orig.InChI: an endpoint, may have fixed-H */
                 pStruct->endpoint[i] && 
                 /*!(pStruct->fixed_H && pStruct->fixed_H[i]) &&*/
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (-) edge */
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {

                iat_SB_O_Minus[num_SB_O_Minus ++] = iat;
                
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            } else
            if ( /* in restored atom: charge=0, has no H, has double non-stereogenic bond, N */
                 num_DB_N_Neutr < MAX_DIFF_FIXH &&
                 at2[iat].charge == 0 && !at2[iat].num_H && !at2[iat].sb_parity[0] &&
                 at2[iat].valence < at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1 &&
                 /* in orig.InChI: an endpoint, has no fixed-H */
                 pStruct->endpoint[i] &&
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (-) edge */
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 &&
                 0 == pBNS->edge[e].forbidden ) {

                iat_DB_N_Neutr[num_DB_N_Neutr ++] = iat;
                
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_DB_N_Neutr, num_SB_O_Minus )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            /* allow stereobonds in rings change */
            if ( forbidden_stereo_edge_mask )
                RemoveForbiddenEdgeMask( pBNS, &FixedLargeRingStereoEdges, forbidden_stereo_edge_mask );

            delta = 1;
            for ( i = 0; i < num_SB_O_Minus && cur_success < num_try; i ++ ) {
                iat = iat_SB_O_Minus[i];
                pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Moved (-) charge to =N- => nDeltaCharge == 1 */
                    /* Flow change on pe (-)charge edge (atom (-)O-) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 08 */
                    }
                } else {
                    pe->forbidden &= forbidden_edge_mask_inv;
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            if ( forbidden_stereo_edge_mask )
                SetForbiddenEdgeMask( pBNS, &FixedLargeRingStereoEdges, forbidden_stereo_edge_mask );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at >= 2 ) {
        /*--------------------------------------------------------*/
        /* case 09: restored: NH2(+)=C--NH2 orig.: NH2-C(+)-NH2   */
        /* FixH:               2     |  2            0  |   0     */
        /* MobH:               0        0            2      2     */
        /* N = N,            taut      taut     non-taut  non-taut*/
        /* Solution: move (+) from NH2(+) to C                    */
        /*--------------------------------------------------------*/
        int iat;
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( (pc2i->c2at[i].nValElectr == 5 && pc2i->c2at[i].nPeriodNum == 1) &&
                 /* orig. InChI info: */
                 !pc2i->c2at[i].endptInChI &&
                 pc2i->c2at[i].nFixHInChI == 0 && pc2i->c2at[i].nMobHInChI &&
                 /* reversed structure info: */
                 pc2i->c2at[i].endptRevrs &&
                 pc2i->c2at[i].nFixHRevrs && !pc2i->c2at[i].nMobHRevrs &&
                 pc2i->c2at[i].nAtChargeRevrs == 1 &&
                 at2[iat].valence + 1 == at2[iat].chem_bonds_valence &&
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {
                EdgeIndex eNC = NO_VERTEX, eCPlusC;
                int       iNH2, iatC, iatNH2, icNH2;
                /* found NH2(+)=; locate =C< and find whether it has -NH2 neighbor */
                for ( j = 0; j < at2[iat].valence; j ++ ) {
                    if ( at2[iat].bond_type[j] == BOND_TYPE_DOUBLE )
                        break;
                }
                if ( j == at2[iat].valence )
                    continue;
                eNC = pBNS->vert[iat].iedge[j]; /* edge NH2(+)=C */
                iatC = at2[iat].neighbor[j];
                if ( pVA[iatC].cNumValenceElectrons != 4 || pVA[iatC].cMetal || at2[iatC].charge ||
                     at2[iatC].valence != 3 || at2[iatC].valence+1 != at2[iatC].chem_bonds_valence ||
                     (eCPlusC=pVA[iatC].nCPlusGroupEdge-1) < 0 || pBNS->edge[eCPlusC].forbidden)
                    continue;
                for ( j = 0; j < at2[iatC].valence; j ++ ) {
                    iatNH2 = at2[iatC].neighbor[j];
                    if ( iatNH2 == iat || pVA[iatNH2].cNumValenceElectrons != 5 ||
                         pVA[iatNH2].cPeriodicRowNumber != 1 || !at2[iatNH2].num_H || at2[iatNH2].charge)
                        continue;
                    icNH2 = pStruct->nAtno2Canon[0][iatNH2];
                    for ( iNH2 = 0; iNH2 < pc2i->len_c2at; iNH2 ++ ) {
                        if ( iatNH2 == pc2i->c2at[iNH2].atomNumber )
                            break;
                    }
                    if ( iNH2 == pc2i->len_c2at )
                        continue;

                    if ( (pc2i->c2at[iNH2].nValElectr == 5 && pc2i->c2at[iNH2].nPeriodNum == 1) &&
                         /* orig. InChI info: */
                         !pc2i->c2at[iNH2].endptInChI &&
                         pc2i->c2at[iNH2].nFixHInChI == 0 && pc2i->c2at[iNH2].nMobHInChI &&
                         /* reversed structure info: */
                         pc2i->c2at[iNH2].endptRevrs &&
                         pc2i->c2at[iNH2].nFixHRevrs && !pc2i->c2at[iNH2].nMobHRevrs &&
                         pc2i->c2at[iNH2].nAtChargeRevrs == 0 &&
                         at2[iatNH2].valence == at2[iatNH2].chem_bonds_valence ) {
                        /* we have found NH2(+)=, =C<, and bond between them */
 
                        if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                            goto exit_function;
                        }
                        if ( (ret = AddToEdgeList( &CurrEdges, eCPlusC, INC_ADD_EDGE )) ) {
                            goto exit_function;
                        }
                        SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                        RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
                        delta = 1;

                        pe   = pBNS->edge + eNC;
                        if ( !pe->flow )
                            continue;
                        pv1 = pBNS->vert + (v1 = pe->neighbor1);
                        pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                        pe->forbidden |= forbidden_edge_mask;
                        pe->flow -= delta; /* add (+) to -NHm */
                        pv1->st_edge.flow -= delta;
                        pv2->st_edge.flow -= delta;
                        pBNS->tot_st_flow -= 2*delta;

                        ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                              &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                        if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                          (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 0 ) {
                            /* Removed (+)charge from -NHn => nDeltaCharge == -1 */
                            /* Flow change on pe (+)charge edge (atom NHm(+)) is not known to RunBnsTestOnce()) */
                            ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                            if ( ret > 0 ) {
                                nNumRunBNS ++;
                                cur_success ++; /* 09 */
                            }
                        } else {
                            pe->flow += delta;
                            pv1->st_edge.flow += delta;
                            pv2->st_edge.flow += delta;
                            pBNS->tot_st_flow += 2*delta;
                        }
                        INCHI_HEAPCHK
                        pe->forbidden &= forbidden_edge_mask_inv;
                        RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
                        CurrEdges.num_edges = 0; /* clear current edge list */
                        break;
                    }
                }
            }
        }
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }


    if ( pc2i->len_c2at >= 2 ) {
        /*--------------------------------------------------------*/
        /* case 10: restored: NH2-X(+)-NH-  orig.: NH2(+)=X-NH-   */
        /* FixH:               0        0            2      1     */
        /* MobH:               2        1            0      0     */
        /* N = N,O,S,Se,Te non-taut  non-taut       taut   taut   */
        /* Solution: move (+) from X(+) to NH2 or NH              */
        /*--------------------------------------------------------*/
        int iat;
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            if ( pc2i->c2at[i].nValue )
                continue;
            iat = pc2i->c2at[i].atomNumber;
            if ( (pc2i->c2at[i].nValElectr == 6 ||
                  (pc2i->c2at[i].nValElectr == 5 && pc2i->c2at[i].nPeriodNum == 1)) &&
                 /* orig. InChI info: */
                 pc2i->c2at[i].endptInChI &&
                 pc2i->c2at[i].nFixHInChI && !pc2i->c2at[i].nMobHInChI &&
                 /* reversed structure info: */
                 !pc2i->c2at[i].endptRevrs &&
                 !pc2i->c2at[i].nFixHRevrs && pc2i->c2at[i].nMobHRevrs &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 &&
                 at2[iat].valence == at2[iat].chem_bonds_valence &&
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {

                EdgeIndex eCPlusC, eCPlusNH2, bContinue=1;
                int       iNH2, iatC, iatNH2, icNH2, j1, j2;
                BNS_EDGE *pe_iat, *pe_iNH2;
                /* found NH2- locate -X(+) and find whether it has another -NH2 neighbor */
                for ( j1 = 0; j1 < at2[iat].valence && bContinue; j1 ++ ) {
                    if ( at2[iat].bond_type[j1] == BOND_TYPE_SINGLE &&
                         at2[iatC = at2[iat].neighbor[j1]].charge == 1 &&
                         (4 <= pVA[iatC].cNumValenceElectrons && pVA[iatC].cNumValenceElectrons <= 6) &&
                         at2[iatC].valence == at2[iatC].chem_bonds_valence &&
                         (eCPlusC=pVA[iatC].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[eCPlusC].forbidden) {
                        /* found a candidate for X; find another NH2 */
                        for ( j2 = 0; j2 < at2[iatC].valence && bContinue; j2 ++ ) {
                            if ( at2[iatC].bond_type[j2] == BOND_TYPE_SINGLE &&
                                 iat != (iatNH2 = at2[iatC].neighbor[j2]) &&
                                 at2[iatNH2].charge == 0 && at2[iatNH2].num_H &&
                                 (pVA[iatNH2].cNumValenceElectrons==5 || pVA[iatNH2].cNumValenceElectrons==6) &&
                                 at2[iatNH2].valence == at2[iatNH2].chem_bonds_valence &&
                                 (eCPlusNH2=pVA[iatNH2].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[eCPlusNH2].forbidden) {
                                for ( iNH2 = 0; iNH2 < pc2i->len_c2at; iNH2 ++ ) {
                                    if ( iatNH2 != pc2i->c2at[iNH2].atomNumber || pc2i->c2at[iNH2].nValue )
                                        continue;
                                    /* check the second -NH */
                                    icNH2 = pStruct->nAtno2Canon[0][iatNH2]; /* canon number -1 */
                                    if ( /* orig. InChI info: */
                                         pc2i->c2at[iNH2].endptInChI &&
                                         pc2i->c2at[iNH2].nFixHInChI && !pc2i->c2at[iNH2].nMobHInChI &&
                                         /* reversed structure info: */
                                         !pc2i->c2at[iNH2].endptRevrs &&
                                         !pc2i->c2at[iNH2].nFixHRevrs && pc2i->c2at[iNH2].nMobHRevrs &&
                                         pc2i->c2at[iNH2].nAtChargeRevrs == 0 ) {
                                        /* we have found NH-X(+)-NH; remove charge from X(+) */
                                        pe_iat  = pBNS->edge + pBNS->vert[iat].iedge[j1];
                                        pe_iNH2 = pBNS->edge + pBNS->vert[iatC].iedge[j2];
                                        /* pick up one of -NH to move (+) to it */
                                        if ( !pe_iat->forbidden && pBNS->edge[e].flow ) {
                                            pe = pBNS->edge + e;
                                        } else
                                        if ( !pe_iNH2->forbidden && pBNS->edge[eCPlusNH2].flow ) {
                                            pe = pBNS->edge + eCPlusNH2;
                                        } else {
                                            continue; /* none of the two -X(+)- bonds may be changed */
                                        }
                                        if ( (ret = AddToEdgeList( &CurrEdges, eCPlusC, INC_ADD_EDGE )) ) {
                                            goto exit_function;
                                        }
                                        SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                                        RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
                                        delta = 1;

                                        pv1 = pBNS->vert + (v1 = pe->neighbor1);
                                        pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                                        /*pe->forbidden |= forbidden_edge_mask;*/
                                        pe->flow -= delta; /* add (+) to -NHm */
                                        pv1->st_edge.flow -= delta;
                                        pv2->st_edge.flow -= delta;
                                        pBNS->tot_st_flow -= 2*delta;

                                        ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                                              &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                                        if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                                          (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == -1 ) {
                                            /* Removed (+)charge from -NHn => nDeltaCharge == -1 */
                                            /* Flow change on pe (+)charge edge (atom NHm(+)) is not known to RunBnsTestOnce()) */
                                            ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                                            if ( ret > 0 ) {
                                                nNumRunBNS ++;
                                                cur_success ++; /* 10 */
                                                bContinue = 0;
                                                pc2i->c2at[i].nValue    = 1;    /* mark as used */
                                                pc2i->c2at[iNH2].nValue = 1; /* mark as used */
                                            }
                                        } else {
                                            pe->flow += delta;
                                            pv1->st_edge.flow += delta;
                                            pv2->st_edge.flow += delta;
                                            pBNS->tot_st_flow += 2*delta;
                                        }
                                        INCHI_HEAPCHK

                                        /*pe->forbidden &= forbidden_edge_mask_inv;*/
                                        RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
                                        CurrEdges.num_edges = 0; /* clear current edge list */
                                        break;
                                    }
                                } /* iNH2: pc2i->c2at[iNH2] cycle */
                            }
                        } /* j2: iatC neighbors cycle */
                    }
                } /* j1: iat neighbors cycle */
            }
        } /* i: pc2i->c2at[i] cycle */
        if ( cur_success ) {
            /*
            for ( i = 0; i < pc2i->len_c2at; i ++ ) {
                pc2i->c2at[i].nValue = 0;
            }
            */
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( /*pc2i->len_c2at >= 1 &&*/ pc2i->nNumTgInChI == 1 && /* ADP in InChI */
         (pc2i->nNumEndpRevrs < pc2i->nNumEndpInChI || pc2i->nNumTgRevrs > 1) ) {
        /*--------------------------------------------------------------*/
        /* case 11: restored: NH(+)=AB-N< OH- orig.  NH-AB=N(+)< OH-    */
        /* FixH:               0       0   0          1      0   1      */
        /* MobH:               1       0   1          0      0   0      */
        /*                 non-taut.                taut        taut    */
        /*                                    ADP: one t-group or more endpoints */
        /* NH(+)= => N, O, S, Se; -N< => N                              */
        /* Solution: move (+) from NH(+) to -N<                         */
        /*--------------------------------------------------------------*/
        int num_SB_Neutr = 0, num_DB_Charged = 0, iat;
        short iat_SB_Neutr[MAX_DIFF_FIXH], iat_DB_Charged[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        /* search for NH(+)= */
        /* search for -N< */
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom: charge=0, has no H, has no double bond, N only */
                 num_DB_Charged < MAX_DIFF_FIXH &&
                 at2[iat].charge == 1 && at2[iat].num_H &&
                 at2[iat].valence < at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 ((pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1) ||
                  pVA[iat].cNumValenceElectrons == 6 ) &&
                 /* in orig.InChI: an endpoint, has fixed-H */
                 /*pStruct->endpoint[i] &&*/
                 (pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 /*!(nMobHInChI && nMobHInChI[i] ) &&*/
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && 0 == pBNS->edge[e].forbidden ) {

                iat_DB_Charged[num_DB_Charged ++] = iat;
                /*
                if ( ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE ) ) {
                    goto exit_function;
                }
                */
            } else
            if ( /* in restored atom: charge=0, has no H, has no double bond, N only */
                 num_SB_Neutr < MAX_DIFF_FIXH &&
                 at2[iat].charge == 0 && !at2[iat].num_H &&
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 (pVA[iat].cNumValenceElectrons == 5 &&
                  pVA[iat].cPeriodicRowNumber == 1 ) &&
                 /* in orig.InChI: an endpoint, has fixed-H */
                 /*pStruct->endpoint[i] &&*/
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && 0 == pBNS->edge[e].forbidden ) {

                iat_SB_Neutr[num_SB_Neutr ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_Neutr, num_DB_Charged )) ) {
            /* detected; attempt to fix */
            BNS_VERTEX *pv1n, *pv2n;
            BNS_EDGE   *pe1n, *pe2n;
            Vertex      v1n, v2n;
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_DB_Charged && cur_success < num_try; i ++ ) {
                iat = iat_DB_Charged[i];
                pe   = pBNS->edge + pVA[iat].nCPlusGroupEdge-1;
                if ( pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                for ( j = pv1->num_adj_edges-1; 0 <= j; j -- ) {
                    pe1n = pBNS->edge + pv1->iedge[j];
                    if ( pe1n->flow && !pe1n->forbidden ) {
                        pv1n = pBNS->vert + (v1n = pe1n->neighbor12 ^ v1);
                        break;
                    }
                }
                if ( j < 0 )
                    continue; /* not found */
                
                for ( j = pv2->num_adj_edges-2; 0 <= j; j -- ) {
                    pe2n = pBNS->edge + pv2->iedge[j];
                    if ( pe2n->flow && !pe2n->forbidden ) {
                        pv2n = pBNS->vert + (v2n = pe2n->neighbor12 ^ v2);
                        break;
                    }
                }
                if ( j < 0 )
                    continue; /* not found */

                pe->flow   += delta;
                pe1n->flow -= delta;
                pe2n->flow -= delta;
                pv1n->st_edge.flow -= delta;
                pv2n->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1n && vPathStart == v2n) ||
                                  (vPathEnd == v2n && vPathStart == v1n)) &&
                                  (nDeltaCharge == 0 || nDeltaCharge == 1) ) {
                    /* before setting flows the structure could be:
                       [NH+ neigh, v1n]=e1n=[NH+,v1]-pe-[+,v2]=e2n=[another at or its chargeStruct]
                       or
                        
                         [NH+ or ChStr, v1n]=pe1n=[NH+ or ChStr, v1]-pe-[+,v2]=pe2n=[at2 or ChStr, v2n]
                                                                     ^    ^    ^
                                                               NH+(+)edge |  N (+) edge: only
                                                                          |  these are not forbidden
                                                                          |
                                                                   hetero (+) vertex

                        After setting flows (* mark radicals, =pe= is forbidden):
                       
                       *[NH+ or ChStr, v1n]-pe1n-[NH+ or ChStr, v1]=pe=[+,v2]-pe2n-[at2 or ChStr, v2n]*
                                                                     ^    ^    ^
                                                               NH+(+)edge |  N (+) edge: only
                                                                          |  these are not forbidden
                                                                          |
                                                                   hetero (+) vertex

                        Flow in
                        pe1n and pe2n will or will not change, depending on the structure.

                        Consider what happens if pe2n changes. It may only increment.
                        If pe2n flow increments then another (+)edge flow dectrements. If
                        [at2 or ChStr, v2n] is at2 then at2 charge would change from (+) to 0,
                        and another N charge would change from 0 to (+), giving tot. change of
                        number of charges  (-1)+(+1)=0. However, if [at2 or ChStr, v2n] is
                        ChargeStruct then at2 will not be on the alt path and only the creation
                        of another (+) will be detected.
                    */
                    /* Removed charge from O(+) => nDeltaCharge == -1 */
                    /* Flow change on pe (+)charge edge (atom NH2) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 11 */
                    }
                } else {
                    pe->flow   -= delta;
                    pe1n->flow += delta;
                    pe2n->flow += delta;
                    pv1n->st_edge.flow += delta;
                    pv2n->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at >= 1 && pc2i->nNumTgInChI == 1 &&
         pc2i->nNumRemHInChI >= -1 && /* 2006-03-03 */
         (pc2i->nNumEndpInChI > pc2i->nNumEndpRevrs || pc2i->nNumTgRevrs > 1) /* ADP in InChI */ ) {
        /*--------------------------------------------------------------*/
        /* case 12: restored: O=AB-N<         original: (-)O-AB=N(+)<   */
        /* FixH:              0    0                     0        0     */
        /* MobH:              0    0                     0        0     */
        /*                   non-taut                   taut            */
        /* O = O, S, Se, N; N = N;                                         */
        /* restored atom O is not tautomeric; original atom O is taut.  */
        /* original struct has 1 t-group; restored has less endpoints   */
        /*                             and/or possibly >1 t-groups      */  
        /* Solution: separate charges between O= and -N<                */
        /*           allow moving charge to N(V) to make it N(IV)(+)    */
        /*--------------------------------------------------------------*/
        int bOnly_N_V = 1;
        cur_success = 0;
        while( 1 ) {
            int num_SB_N_Neutr = 0, num_DB_O = 0, iat, num_N_V=0, bN_V;
            short iat_SB_N_Neutr[MAX_DIFF_FIXH], iat_DB_O[MAX_DIFF_FIXH];
            AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
            inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                                 pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
            S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                                   pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
            cur_success = 0;
            for ( i = 0; i < pc2i->len_c2at; i ++ ) {
                iat = pc2i->c2at[i].atomNumber;
                if ( /* orig. InChI info: -O(-) */
                     num_DB_O < MAX_DIFF_FIXH &&
                     (pc2i->c2at[i].nValElectr == 6 /* O, S, Se, Te */ ||
                      (pc2i->c2at[i].nValElectr == 5 &&
                      pc2i->c2at[i].nPeriodNum == 1) /* N */ ) &&
                     pc2i->c2at[i].endptInChI &&
                     (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                     pc2i->c2at[i].nFixHInChI == 0 && pc2i->c2at[i].nMobHInChI == 0 &&
                     /* reversed structure info: */
                     !pc2i->c2at[i].endptRevrs &&
                     pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs == 0 &&
                     pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                     ((pc2i->c2at[i].nValElectr == 6)? 
                           (at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 2):
                      (pc2i->c2at[i].nValElectr == 5)?
                           (at2[iat].valence == 2 && at2[iat].chem_bonds_valence == 3):
                           0)) {
                
                    iat_DB_O[num_DB_O ++] = iat;
                    /*
                    if ( ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE ) ) {
                        goto exit_function;
                    }
                    */
                }
            }
            for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
                iat = nCanon2AtnoRevrs[i];
                bN_V = 0;
                if ( /* in restored atom N: charge=0, no H, has no double bond, not an endpoint */
                     num_SB_N_Neutr < MAX_DIFF_FIXH &&
                     at2[iat].charge == 0 && !at2[iat].num_H &&
                     (at2[iat].valence == at2[iat].chem_bonds_valence ||
                     (bN_V = at2[iat].valence+2 == at2[iat].chem_bonds_valence)) &&
                     !pVA[iat].cMetal &&
                     pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1 &&
                     !(at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint) &&
                     /* in orig.InChI: not an endpoint, has no H */
                     !pStruct->endpoint[i] &&
                     !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                     !(nMobHInChI && nMobHInChI[i]) &&
                     /* has (+) edge */
                     (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {

                    if ( bOnly_N_V && bN_V &&
                         NO_VERTEX != (j = GetChargeFlowerUpperEdge( pBNS, pVA, e )) &&
                         !pBNS->edge[j].forbidden && !pBNS->edge[j].flow ) {
                        if ( !num_N_V ) {
                            /* switch to N(V) only mode */
                            CurrEdges.num_edges = 0;
                            num_SB_N_Neutr = 0;
                        }
                        iat_SB_N_Neutr[num_SB_N_Neutr ++] = iat;
                        num_N_V ++;
                        if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                            goto exit_function;
                        }
                        if ( (ret = AddToEdgeList( &CurrEdges, j, INC_ADD_EDGE )) ) {
                            goto exit_function;
                        }
                    } else
                    if ( !num_N_V ) {
                        iat_SB_N_Neutr[num_SB_N_Neutr ++] = iat;
                        if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                            goto exit_function;
                        }
                        /* in addition, permit N(V)=>N(IV)(+) change by allowing charge flower edge change flow */
                        if ( bN_V && NO_VERTEX != (j = GetChargeFlowerUpperEdge( pBNS, pVA, e )) &&
                             !pBNS->edge[j].forbidden && !pBNS->edge[j].flow ) {
                            if ( (ret = AddToEdgeList( &CurrEdges, j, INC_ADD_EDGE )) ) {
                                goto exit_function;
                            }
                        }
                    }
                }
            }
            if ( (num_try = inchi_min( num_SB_N_Neutr, num_DB_O )) ) {
                /* detected; attempt to fix */
                BNS_EDGE *pe_CMinus;
                SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
                delta = 1;
                for ( i = 0; i < num_DB_O && cur_success < num_try; i ++ ) {
                    iat = iat_DB_O[i];
                    pe_CMinus = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                    pe_CMinus->forbidden &= forbidden_edge_mask_inv;

                    pe   = pBNS->edge + pBNS->vert[iat].iedge[0]; /* double bond O=...*/
                    if ( !pe->flow )
                        continue;
                    pv1 = pBNS->vert + (v1 = pe->neighbor1);
                    pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                    pe->forbidden |= forbidden_edge_mask; /* change bond O=X to O(rad)-X(rad) */
                    pe->flow -= delta;
                    pv1->st_edge.flow -= delta;
                    pv2->st_edge.flow -= delta;
                    pBNS->tot_st_flow -= 2*delta;

                    ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                          &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                    if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                      (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 2 ) {
                        /* Added (-) charge to =O and (+) charge to N => nDeltaCharge == 2 */
                        ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                        if ( ret > 0 ) {
                            nNumRunBNS ++;
                            cur_success ++; /* 12 */
                        }
                    } else {
                        pe->flow += delta;
                        pv1->st_edge.flow += delta;
                        pv2->st_edge.flow += delta;
                        pBNS->tot_st_flow += 2*delta;
                    }
                    pe->forbidden        &= forbidden_edge_mask_inv; /* allow changes to O=X bond */
                    INCHI_HEAPCHK
                }
                RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
            }
            CurrEdges.num_edges = 0; /* clear current edge list */
            if ( cur_success ) {
                tot_succes += cur_success;
                /* recalculate InChI from the structure */
                if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                                ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                    goto exit_function;
                }
                if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                    goto exit_function;
                }
                if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                    goto exit_function;  /* no fixed-H found */
                }
                if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                    goto exit_function;
                }
                if ( !pc2i->bHasDifference ) {
                    goto exit_function; /* nothing to do */
                }
                break;
            } else
            if ( bOnly_N_V ) {
                bOnly_N_V = 0;
            } else {
                break;
            }
        }
    }

    if ( pc2i->nNumTgDiffMinus /*|| pc2i->nNumTgDiffH */ /* no ADP in InChI needed */ ) {
        /*--------------------------------------------------------------*/
        /*                         |                            |       */
        /* case 13: restored: O=AB=N=         original: (-)O-AB-N(+)=   */
        /* FixH:              0    0                     0        0     */
        /* MobH:              0    0                     0        0     */
        /*                        non-taut              taut   non-taut */
        /* O = O, S, Se, N; N = N, P, ...                               */
        /* t-group in original has same num. endpoints                  */
        /*       same num_H and less (-) than in the restored structure */
        /* original atom O is tautomeric, N is not taut in both         */
        /* original struct has 1 t-group; restored has less endpoints   */
        /*                             and/or possibly >1 t-groups      */  
        /* Solution: separate charges between O= and -N<                */
        /*           allow moving charge to N(V) to make it N(IV)(+)    */
        /*--------------------------------------------------------------*/
        int itg;
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;

        S_CHAR   *num_Fixed_H_Revrs = pStruct->pOneINChI[0]->nNum_H_fixed? pStruct->pOneINChI[0]->nNum_H_fixed : NULL;
        S_CHAR   *pnMobHRevrs = (pStruct->pOneINChI[1] && pStruct->pOneINChI[1]->nNum_H)?
                                   pStruct->pOneINChI[1]->nNum_H : 
                                (pStruct->pOneINChI[0] && pStruct->pOneINChI[0]->nNum_H)?
                                   pStruct->pOneINChI[0]->nNum_H : NULL;
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        /* find whether this may help */
        for ( itg = 0; itg < pStruct->ti.num_t_groups && itg < pStruct->One_ti.num_t_groups; itg ++ ) {
            if ( pStruct->ti.t_group[itg].nNumEndpoints == pStruct->One_ti.t_group[itg].nNumEndpoints &&
                 pStruct->ti.t_group[itg].num[0] - pStruct->ti.t_group[itg].num[1] == 
                 pStruct->One_ti.t_group[itg].num[0] - pStruct->One_ti.t_group[itg].num[1] &&
                 pStruct->ti.t_group[itg].num[1] > pStruct->One_ti.t_group[itg].num[1]) {
                /* restored InChI t-group has more (-) and same number of H */

                int num_SB_N_Neutr = 0, num_DB_O = 0, iat;
                short iat_SB_N_Neutr[MAX_DIFF_FIXH], iat_DB_O[MAX_DIFF_FIXH];
                cur_success = 0;
                for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
                    iat = nCanon2AtnoRevrs[i];
                    if ( /* orig. InChI info: -O(-) */
                         num_DB_O < MAX_DIFF_FIXH &&
                         (pVA[i].cNumValenceElectrons == 6 /* O, S, Se, Te */ ) &&
                         pStruct->endpoint[i] == itg+1 &&
                         (e=pVA[i].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                         !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                         !(nMobHInChI && nMobHInChI[i]) &&
                         /* reversed structure info: */
                         /*!pc2i->c2at[i].endptRevrs &&*/
                         !(num_Fixed_H_Revrs && num_Fixed_H_Revrs[iat]) &&
                         !(pnMobHRevrs && pnMobHRevrs[iat]) &&
                         at2[iat].charge == 0 && at2[iat].num_H == 0 &&
                         at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 2 ) {
            
                        iat_DB_O[num_DB_O ++] = iat;
                        /*
                        if ( ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE ) ) {
                            goto exit_function;
                        }
                        */
                    } else
                    if ( /* in restored atom N: charge=0, no H, has no double bond, not an endpoint */
                         num_SB_N_Neutr < MAX_DIFF_FIXH &&
                         at2[iat].charge == 0 && !at2[iat].num_H &&
                         /*at2[iat].valence == at2[iat].chem_bonds_valence ||*/
                         (at2[iat].valence==4 && at2[iat].chem_bonds_valence==5) &&
                         !pVA[iat].cMetal &&
                         pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber >= 1 &&
                         !(at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint) &&
                         /* in orig.InChI: not an endpoint, has no H */
                         !pStruct->endpoint[i] &&
                         !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                         !(nMobHInChI && nMobHInChI[i]) &&
                         /* has (+) edge */
                         (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {

                        iat_SB_N_Neutr[num_SB_N_Neutr ++] = iat;
                        if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                            goto exit_function;
                        }
                    }
                }
                if ( (num_try = inchi_min( num_SB_N_Neutr, num_DB_O )) ) {
                    /* detected; attempt to fix */
                    BNS_EDGE *pe_CMinus;
                    SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                    RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
                    delta = 1;
                    for ( i = 0; i < num_DB_O && cur_success < num_try; i ++ ) {
                        iat = iat_DB_O[i];
                        pe_CMinus = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                        pe_CMinus->forbidden &= forbidden_edge_mask_inv;

                        pe   = pBNS->edge + pBNS->vert[iat].iedge[0]; /* double bond O=...*/
                        if ( !pe->flow )
                            continue;
                        pv1 = pBNS->vert + (v1 = pe->neighbor1);
                        pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                        pe->forbidden |= forbidden_edge_mask; /* change bond O=X to O(rad)-X(rad) */
                        pe->flow -= delta;
                        pv1->st_edge.flow -= delta;
                        pv2->st_edge.flow -= delta;
                        pBNS->tot_st_flow -= 2*delta;

                        ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                              &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                        if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                          (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 2 ) {
                            /* Added (-) charge to =O and (+) charge to N => nDeltaCharge == 2 */
                            ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                            if ( ret > 0 ) {
                                nNumRunBNS ++;
                                cur_success ++; /* 13 */
                            }
                        } else {
                            pe->flow += delta;
                            pv1->st_edge.flow += delta;
                            pv2->st_edge.flow += delta;
                            pBNS->tot_st_flow += 2*delta;
                        }
                        pe->forbidden        &= forbidden_edge_mask_inv; /* allow changes to O=X bond */
                        INCHI_HEAPCHK
                    }
                    RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
                }
                CurrEdges.num_edges = 0; /* clear current edge list */
                if ( cur_success ) {
                    tot_succes += cur_success;
                    /* recalculate InChI from the structure */
                    if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                                    ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                        goto exit_function;
                    }
                    if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                        goto exit_function;
                    }
                    if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                        goto exit_function;  /* no fixed-H found */
                    }
                    if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                        goto exit_function;
                    }
                    if ( !pc2i->bHasDifference ) {
                        goto exit_function; /* nothing to do */
                    }
                    break;
                }/* else
                if ( bOnly_N_V ) {
                    bOnly_N_V = 0;
                }
                */
                break;
            }
        }
    }

    if ( ((pc2i->nNumTgInChI <= 1 &&
        pc2i->nNumRemHInChI > pc2i->nNumRemHRevrs) || pc2i->len_c2at) &&
         bHas_N_V( at2, pStruct->num_atoms) ) {
        /*-----------------------------------------------------------------*/
        /*                         |                         |             */
        /* case 14: restored:-N=AB=N=CD-XH original: (-)N-AB-N(+)=CD-XH    */
        /* FixH:              0    0   0/1              0            1     */
        /* MobH:              0    0   1/0              0            0     */
        /*                   non-taut  n/t             any  non     any    */
        /*                                                  taut           */
        /* X = O, S, Se, N; N = N                                          */
        /* t-group in original may have more (-) than in restored          */
        /*       same num_H and less (-) than in the restored structure    */
        /* atom N(V)/N(IV)(+) is not taut in both                          */
        /* The following transformation should be possible:                */
        /*        |                         |                              */
        /*   N=AB=N=CD-XH    ->     (-)N-AB-N-CD=XH(+)                     */
        /* This allows ADP to remove H(+) from -XH                         */
        /* As the result, the original structure has 0 or 1 t-group        */
        /* Solution: separate charges between -N(III)= and  N(V)           */
        /*-----------------------------------------------------------------*/
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;

        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        int num_N_V = 0, iat, i1, i2, i3, e1Flower, e1Plus, e2Plus, e2Minus, e3Plus;
        int max_success = pc2i->nNumRemHInChI - pc2i->nNumRemHRevrs;
        short iat_N_V_Array[MAX_DIFF_FIXH];
        EDGE_LIST iat_X_List, iat_N_III_List;
        AllocEdgeList( &iat_X_List, EDGE_LIST_CLEAR );
        AllocEdgeList( &iat_N_III_List, EDGE_LIST_CLEAR );
        cur_success = 0;
        ret = 0;
        for ( i = 0; i < pStruct->num_atoms; i ++ ) {
            iat = nCanon2AtnoRevrs[i];
            /* search for N(V), 3 bonds */
            if ( /* restored structure */
                 num_N_V < MAX_DIFF_FIXH &&
                 at2[iat].chem_bonds_valence == 5 && at2[iat].valence == 3 &&
                 !at2[iat].charge && !at2[iat].radical &&
                 pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1 &&
                 !( at_Mobile_H_Revrs && at_Mobile_H_Revrs[i].endpoint ) &&
                 !at2[iat].num_H &&
                 (e = pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pBNS->edge[e].flow /* no charge */ &&
                 NO_VERTEX != (j = GetChargeFlowerUpperEdge( pBNS, pVA, e )) && !pBNS->edge[j].forbidden &&
                 !pBNS->edge[j].flow /* neutral, valence=5 */ &&
                 /* orig. InChI */
                 !pStruct->endpoint[i] &&
                 !(nMobHInChI && nMobHInChI[i]) && !pStruct->fixed_H[i] ) {
                iat_N_V_Array[num_N_V ++] = iat;
            } else
            /* search for -N= */
            if ( /* restored structure */
                 at2[iat].chem_bonds_valence == 3 && at2[iat].valence == 2 &&
                 !at2[iat].charge && !at2[iat].radical &&
                 pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1 &&
                 !(at_Mobile_H_Revrs && at_Mobile_H_Revrs[i].endpoint ) &&
                 !at2[iat].num_H &&
                 (e = pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 !pBNS->edge[e].flow /* no charge */ &&
                 /* orig. InChI */
                 /*!pStruct->endpoint[i] &&*/
                 !(nMobHInChI && nMobHInChI[i]) && !pStruct->fixed_H[i] ) {

                if ( (ret = AddToEdgeList( &iat_N_III_List, iat, 32 )) ) {
                    goto exit_case_14;
                }
            } else
            /* search for -OH -NH-, -NH2 */
            if ( /* restored structure */
                 at2[iat].chem_bonds_valence == at2[iat].valence &&
                 !at2[iat].charge && !at2[iat].radical &&
                 ((pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1) ||
                 pVA[iat].cNumValenceElectrons == 6 ) &&
                 at2[iat].num_H &&
                 (e = pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pBNS->edge[e].flow /* no charge */ &&
                 /* orig. InChI */
                 !(nMobHInChI && nMobHInChI[i]) && pStruct->fixed_H[i] ) {

                if ( (ret = AddToEdgeList( &iat_X_List, iat, 32 )) ) {
                    goto exit_case_14;
                }
            }
        }
        if ( !max_success ) {
            max_success = inchi_min( num_N_V, iat_N_III_List.num_edges );
            max_success = inchi_min( max_success, iat_X_List.num_edges );
        }
        if ( num_N_V && iat_N_III_List.num_edges && iat_X_List.num_edges ) {
            for ( i1 = 0; i1 < num_N_V && cur_success < max_success; i1 ++ ) {
                int iat_N_V = iat_N_V_Array[i1];
                if ( NO_VERTEX == iat_N_V ||
                     0 >= (e1Plus = pVA[iat_N_V].nCPlusGroupEdge-1) ||
                     NO_VERTEX == (e1Flower = GetChargeFlowerUpperEdge( pBNS, pVA, e1Plus )) ||
                     1 != pBNS->edge[e1Plus].flow ||
                     0 != pBNS->edge[e1Flower].flow ) {
                    continue;
                }
                for ( i2 = iat_N_III_List.num_edges-1; 0 <= i2 && cur_success < max_success; i2 -- ) {
                    int iat_N_III = iat_N_III_List.pnEdges[i2];
                    if ( NO_VERTEX == iat_N_III ||
                         0 >= (e2Minus = pVA[iat_N_III].nCMinusGroupEdge-1) ||
                         0 >= (e2Plus  = pVA[iat_N_III].nCPlusGroupEdge-1) ||
                         0 != pBNS->edge[e2Minus].flow ||
                         1 != pBNS->edge[e2Plus].flow ) {
                        /* do not consider this atom anymore */
                        iat_N_III_List.pnEdges[i2] = NO_VERTEX;
                        continue;
                    }
                    for ( i3 = iat_X_List.num_edges-1; 0 <= i3 && cur_success < max_success; i3 -- ) {
                        int iat_X = iat_X_List.pnEdges[i3];
                        BNS_VERTEX *pv1n, *pv2n;
                        BNS_EDGE   *pe1n, *pe2n, *pe1Plus, *pe2Minus, *pe3Plus;
                        Vertex      v1n, v2n;
                        ret = 0;
                        if ( NO_VERTEX == iat_X ||
                             0 >= (e3Plus  = pVA[iat_X].nCPlusGroupEdge-1) ||
                             1 != pBNS->edge[e3Plus].flow ) {
                            /* do not consider this atom anymore */
                            iat_X_List.pnEdges[i3] = NO_VERTEX;
                            continue;
                        }
                        /* all is ready to check whether the following applies:
                           forbid changes of all charges and N,P,... flowers
                           allow to change edges: e2Minus, e3Plus
                           Increment flow in e1Flower
                           The result should be: increase in number of charges by 2
                        */
                        pe1Plus  = pBNS->edge + e1Plus;  /* N(V) positive charge edge */
                        pe2Minus = pBNS->edge + e2Minus; /* =N- negative charge edge */
                        pe3Plus  = pBNS->edge + e3Plus;  /* -XH positive charge edge */
                        pe       = pBNS->edge + e1Flower; /* N(V) flower edge */
                        pv1 = pBNS->vert + (v1 = pe->neighbor1);
                        pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);
                        for ( j = pv1->num_adj_edges-1; 0 <= j; j -- ) {
                            pe1n = pBNS->edge + pv1->iedge[j];
                            if ( pe1n->flow && !pe1n->forbidden && pe1n != pe1Plus ) {
                                pv1n = pBNS->vert + (v1n = pe1n->neighbor12 ^ v1);
                                break;
                            }
                        }
                        if ( j < 0 )
                            continue; /* not found -- should not happen */
                        for ( j = pv2->num_adj_edges-1; 0 <= j; j -- ) { /* was -2; changed 2006-2-28 12:35pm*/
                            pe2n = pBNS->edge + pv2->iedge[j];
                            if ( pe2n->flow && !pe2n->forbidden && pe2n != pe1Plus ) {
                                pv2n = pBNS->vert + (v2n = pe2n->neighbor12 ^ v2);
                                break;
                            }
                        }
                        if ( j < 0 )
                            continue; /* not found -- should not happen */
                        delta = 1;
                        pe->flow           += delta;
                        pe1n->flow         -= delta;
                        pe2n->flow         -= delta;
                        pv1n->st_edge.flow -= delta;
                        pv2n->st_edge.flow -= delta;
                        pBNS->tot_st_flow  -= 2*delta;
                        
                        SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                        SetForbiddenEdgeMask( pBNS, &OtherNFlowerEdges, forbidden_edge_mask );

                        /* allow two charges to change */
                        pe2Minus->forbidden &= forbidden_edge_mask_inv;
                        pe3Plus->forbidden  &= forbidden_edge_mask_inv;
                        /* test #1 */
                        ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                              &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
                        INCHI_HEAPCHK
                        if ( ret < 0 ) {
                            goto exit_case_14;
                        } else
                        if ( ret == 1 && ((vPathEnd == v1n && vPathStart == v2n) ||
                                          (vPathEnd == v2n && vPathStart == v1n)) &&
                                          nDeltaCharge == 2 ) {
                            ; /* success */
                        } else {
                            ret = 0;
                        }
                        /* restore BNS */
                        pe2Minus->forbidden |= forbidden_edge_mask;
                        pe3Plus->forbidden  |= forbidden_edge_mask;
                        pe->flow           -= delta;
                        pe1n->flow         += delta;
                        pe2n->flow         += delta;
                        pv1n->st_edge.flow += delta;
                        pv2n->st_edge.flow += delta;
                        pBNS->tot_st_flow  += 2*delta;
                        if ( ret == 1 ) {
                            /* test #2: check if charge separation is possible */
                            pe->flow           += delta;
                            pe1n->flow         -= delta;
                            pe2n->flow         -= delta;
                            pv1n->st_edge.flow -= delta;
                            pv2n->st_edge.flow -= delta;
                            pBNS->tot_st_flow  -= 2*delta;

                            /* allow two charges (N(V) and N(III)) to change */
                            pe2Minus->forbidden &= forbidden_edge_mask_inv;
                            pe1Plus->forbidden  &= forbidden_edge_mask_inv;
                            /* test #2 */
                            ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                              &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );
                            if ( ret == 1 && ((vPathEnd == v1n && vPathStart == v2n) ||
                                              (vPathEnd == v2n && vPathStart == v1n)) &&
                                              nDeltaCharge == 2 ) {
                                /* success; actually change charges */
                                ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                                if ( ret > 0 ) {
                                    nNumRunBNS ++;
                                    cur_success ++; /* 14 */
                                }
                            }
                            if ( ret <= 0 ) {
                                /* failed: restore BNS flow */
                                pe->flow           -= delta;
                                pe1n->flow         += delta;
                                pe2n->flow         += delta;
                                pv1n->st_edge.flow += delta;
                                pv2n->st_edge.flow += delta;
                                pBNS->tot_st_flow  += 2*delta;
                            }
                            INCHI_HEAPCHK
                        }
                        RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
                        RemoveForbiddenEdgeMask( pBNS, &OtherNFlowerEdges, forbidden_edge_mask  );
                        if ( ret > 0 ) {
                            /* do not repeat for the same atoms */
                            iat_N_V_Array[i1] = NO_VERTEX;
                            iat_N_III_List.pnEdges[i2] = NO_VERTEX;
                            iat_X_List.pnEdges[i3] = NO_VERTEX;
                        }
                        if ( ret < 0 ) {
                            goto exit_case_14;
                        }
                        if ( ret > 0 ) {
                            break;
                        }
                    } /* i3 cycle */
                    if ( ret > 0 ) {
                        break;
                    }
                } /* i2 cycle */
            }
        }
exit_case_14:
        AllocEdgeList( &iat_X_List, EDGE_LIST_FREE );
        AllocEdgeList( &iat_N_III_List, EDGE_LIST_FREE );
        RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        RemoveForbiddenEdgeMask( pBNS, &OtherNFlowerEdges, forbidden_edge_mask  );
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( ret < 0 ) {
            goto exit_function;
        }
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }


    if ( pc2i->nNumTgMRevrs > pc2i->nNumTgMInChI ||
         pc2i->nNumRemHRevrs < pc2i->nNumRemHInChI ||
         pc2i->nNumEndpRevrs < pc2i->nNumEndpInChI ||
         (pc2i->nNumTgInChI <= 1 && pc2i->nNumTgRevrs > pc2i->nNumTgInChI) ) {
        /*--------------------------------------------------------------*/
        /* case 15: restored: -(+)O=AB-N<  orig: -O-AB=N(+)<            */
        /* (a) restored t-groups have more (-) than in original InChI   */
        /* (b) Mobile-H    charge: restored > original InChI *and*      */
        /*              removed H: restored < original InChI            */
        /* (c) restored t-groups have less endpnoits than in orig InChI */
        /* O = O, S, Se, Te; N = N                                      */
        /* Solution: move (+) from -O(+)= to -N<                        */
        /*--------------------------------------------------------------*/
        int num_SB_Neutr = 0, num_DB_Charged = 0, iat;
        short iat_SB_Neutr[MAX_DIFF_FIXH], iat_DB_Charged[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        /* search for -O(+)= */
        /* search for -N< */
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* -O(+)= in restored atom: charge=1, has no H, a double bond */
                 num_DB_Charged < MAX_DIFF_FIXH &&
                 at2[iat].charge == 1 && !at2[iat].num_H &&
                 at2[iat].valence < at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 (pVA[iat].cNumValenceElectrons == 6 ) &&
                 /* in orig.InChI: an endpoint, has fixed-H */
                 /*pStruct->endpoint[i] &&*/
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && 0 == pBNS->edge[e].forbidden ) {

                iat_DB_Charged[num_DB_Charged ++] = iat;
                /*
                if ( ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE ) ) {
                    goto exit_function;
                }
                */
            } else
            if ( /* -N< in restored atom: charge=0, has no H, has no double bond, N only */
                 num_SB_Neutr < MAX_DIFF_FIXH &&
                 at2[iat].charge == 0 && !at2[iat].num_H &&
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 (pVA[iat].cNumValenceElectrons == 5 &&
                  pVA[iat].cPeriodicRowNumber == 1 ) &&
                 /* in orig.InChI: an endpoint, has fixed-H */
                 /*pStruct->endpoint[i] &&*/
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && 0 == pBNS->edge[e].forbidden ) {

                iat_SB_Neutr[num_SB_Neutr ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_Neutr, num_DB_Charged )) ) {
            /* detected; attempt to fix */
            BNS_VERTEX *pv1n, *pv2n;
            BNS_EDGE   *pe1n, *pe2n;
            Vertex      v1n, v2n;
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_DB_Charged && cur_success < num_try; i ++ ) {
                iat = iat_DB_Charged[i];
                pe   = pBNS->edge + pVA[iat].nCPlusGroupEdge-1;
                if ( pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                for ( j = pv1->num_adj_edges-1; 0 <= j; j -- ) {
                    pe1n = pBNS->edge + pv1->iedge[j];
                    if ( pe1n->flow && !pe1n->forbidden ) {
                        pv1n = pBNS->vert + (v1n = pe1n->neighbor12 ^ v1);
                        break;
                    }
                }
                if ( j < 0 )
                    continue; /* not found */
                
                for ( j = pv2->num_adj_edges-1; 0 <= j; j -- ) { /* was -2; changed 2006-2-28 12:35pm*/
                    pe2n = pBNS->edge + pv2->iedge[j];
                    if ( pe2n->flow && !pe2n->forbidden ) {
                        pv2n = pBNS->vert + (v2n = pe2n->neighbor12 ^ v2);
                        break;
                    }
                }
                if ( j < 0 )
                    continue; /* not found */

                pe->flow   += delta;
                pe1n->flow -= delta;
                pe2n->flow -= delta;
                pv1n->st_edge.flow -= delta;
                pv2n->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1n && vPathStart == v2n) ||
                                  (vPathEnd == v2n && vPathStart == v1n)) &&
                                  (nDeltaCharge == 0 || nDeltaCharge == 1) ) {
                    /* Moved charge from O(+) to -N< => nDeltaCharge == 1 or 0 if pe2n = -N< charge edge */
                    /* Flow change on pe (+)charge edge (atom NH2) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 15 */
                    }
                } else {
                    pe->flow   -= delta;
                    pe1n->flow += delta;
                    pe2n->flow += delta;
                    pv1n->st_edge.flow += delta;
                    pv2n->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->nNumTgDiffMinus ) {
        /*----------------------------------------------------------------*/
        /* case 16: restored: O=X-NH(-)      orig.:  O(-)-X=NH            */
        /*            t-group: (H,-)                  (2H)                */
        /* O(-) = S, Se, Te; N = N;                                       */
        /* Solution: move (-) from O(-) to -NH(-)                         */
        /*----------------------------------------------------------------*/
        int num_SB_N_Minus = 0, num_DB_O_Neutr = 0, iat, itg;
        short iat_SB_N_Minus[MAX_DIFF_FIXH], iat_DB_O_Neutr[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        for ( itg = 0; itg < pStruct->ti.num_t_groups && itg < pStruct->One_ti.num_t_groups; itg ++ ) {
            if ( pStruct->ti.t_group[itg].nNumEndpoints != pStruct->One_ti.t_group[itg].nNumEndpoints ||
                 pStruct->ti.t_group[itg].num[1]  >= pStruct->One_ti.t_group[itg].num[1] ) {
                continue;
            }
            CurrEdges.num_edges = num_SB_N_Minus = num_DB_O_Neutr = 0;
            cur_success = 0;
            for ( j = 0, k = pStruct->One_ti.t_group[itg].nFirstEndpointAtNoPos;
                    j < pStruct->One_ti.t_group[itg].nNumEndpoints; j ++ ) {
                i = pStruct->One_ti.nEndpointAtomNumber[k+j]; /* canonical number in restored struct. */
                iat = nCanon2AtnoRevrs[i];
                if ( /* in restored atom: charge=0, has no H, has double bond, O, S, Se, Te */
                     num_DB_O_Neutr < MAX_DIFF_FIXH &&
                     at2[iat].charge == 0 && !at2[iat].num_H &&
                     at2[iat].valence < at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                     pVA[iat].cNumValenceElectrons == 6 &&
                     /* in orig.InChI: an endpoint, may have fixed-H */
                     pStruct->endpoint[i] && 
                     /*!(pStruct->fixed_H && pStruct->fixed_H[i]) &&*/
                     !(nMobHInChI && nMobHInChI[i] ) &&
                     /* has (-) edge */
                     (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {

                    iat_DB_O_Neutr[num_DB_O_Neutr ++] = iat;
                    
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                    
                } else
                if ( /* in restored atom: charge=-1, has H, has double bond, N */
                     num_SB_N_Minus < MAX_DIFF_FIXH &&
                     at2[iat].charge == -1 && at2[iat].num_H &&
                     at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                     pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1 &&
                     /* in orig.InChI: an endpoint, has no fixed-H */
                     pStruct->endpoint[i] &&
                     (pStruct->fixed_H && pStruct->fixed_H[i]) &&
                     !(nMobHInChI && nMobHInChI[i] ) &&
                     /* has (-) edge */
                     (e=pVA[iat].nCMinusGroupEdge-1) >= 0 &&
                     0 == pBNS->edge[e].forbidden ) {

                    iat_SB_N_Minus[num_SB_N_Minus ++] = iat;
                    /*
                    if ( ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE ) ) {
                        goto exit_function;
                    }
                    */
                }
            }
            if ( (num_try = inchi_min( num_SB_N_Minus, num_DB_O_Neutr )) ) {
                /* detected; attempt to fix */
                SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
                /* allow stereobonds in rings change */
                /*
                if ( forbidden_stereo_edge_mask )
                    RemoveForbiddenEdgeMask( pBNS, &FixedLargeRingStereoEdges, forbidden_stereo_edge_mask );
                */
                delta = 1;
                for ( i = 0; i < num_SB_N_Minus && cur_success < num_try; i ++ ) {
                    iat = iat_SB_N_Minus[i];
                    pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                    if ( !pe->flow )
                        continue;
                    pv1 = pBNS->vert + (v1 = pe->neighbor1);
                    pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                    /*pe->forbidden |= forbidden_edge_mask;*/
                    pe->flow -= delta;
                    pv1->st_edge.flow -= delta;
                    pv2->st_edge.flow -= delta;
                    pBNS->tot_st_flow -= 2*delta;

                    ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                          &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                    if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                      (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                        /* Moved (-) charge to =O => nDeltaCharge == 1 */
                        /* Flow change on pe (-)charge edge (atom -NH(-)) is not known to RunBnsTestOnce()) */
                        ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                        if ( ret > 0 ) {
                            nNumRunBNS ++;
                            cur_success ++; /* 16 */
                        }
                    } else {
                        pe->forbidden &= forbidden_edge_mask_inv;
                        pe->flow += delta;
                        pv1->st_edge.flow += delta;
                        pv2->st_edge.flow += delta;
                        pBNS->tot_st_flow += 2*delta;
                    }
                    INCHI_HEAPCHK
                }
                RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                /*
                if ( forbidden_stereo_edge_mask )
                    SetForbiddenEdgeMask( pBNS, &FixedLargeRingStereoEdges, forbidden_stereo_edge_mask );
                */
            }
            CurrEdges.num_edges = 0; /* clear current edge list */
            if ( cur_success ) {
                tot_succes += cur_success;
                /* recalculate InChI from the structure */
                if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                                ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                    goto exit_function;
                }
                if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                    goto exit_function;
                }
                if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                    goto exit_function;  /* no fixed-H found */
                }
                if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                    goto exit_function;
                }
                if ( !pc2i->bHasDifference ) {
                    goto exit_function; /* nothing to do */
                }
            }
        }
    }

    if ( pc2i->nNumRemHInChI < pc2i->nNumRemHRevrs ) {
        /*--------------------------------------------------------------*/
        /* case 17: restored: OH(+)=AB-O-     orig.  HO-AB=O(+)-        */
        /* number of removed H:  n+m                     n              */
        /* OH(+) = N, O, S, Se; -O- = P,As,O,S,Se,Te,F,Cl,Br,I          */
        /* Solution: move (+) from OH(+) to -O-                         */
        /*--------------------------------------------------------------*/
        int num_SB_Neutr = 0, num_DB_Charged = 0, iat;
        short iat_SB_Neutr[MAX_DIFF_FIXH], iat_DB_Charged[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        cur_success = 0;
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom: charge=+1, has H, has double bond, N, O, S, Se, Te */
                 num_DB_Charged < MAX_DIFF_FIXH &&
                 at2[iat].charge == 1 && at2[iat].num_H &&
                 at2[iat].valence < at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 (pVA[iat].cNumValenceElectrons == 6 ||
                  (pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber == 1)) &&
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden ) {

                iat_DB_Charged[num_DB_Charged ++] = iat;
                /*
                if ( ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE ) ) {
                    goto exit_function;
                }
                */
            } else
            if ( /* in restored atom: charge=0, has no H, has no double bond, N, P, O, S, Se, Te */
                 num_SB_Neutr < MAX_DIFF_FIXH &&
                 at2[iat].charge == 0 && !at2[iat].num_H &&
                 at2[iat].valence == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 (pVA[iat].cNumValenceElectrons == 6 || pVA[iat].cNumValenceElectrons == 7 ||
                  (pVA[iat].cNumValenceElectrons == 5 && pVA[iat].cPeriodicRowNumber > 1) ) &&
                 /* in orig.InChI: not an endpoint */
                 !pStruct->endpoint[i] &&
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 !(nMobHInChI && nMobHInChI[i] ) &&
                 /* has (+) edge */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 &&
                 0 == pBNS->edge[e].forbidden ) {

                iat_SB_Neutr[num_SB_Neutr ++] = iat;
                
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_Neutr, num_DB_Charged )) ) {
            BNS_VERTEX *pv1n, *pv2n;
            BNS_EDGE   *pe1n, *pe2n;
            Vertex      v1n, v2n;

            num_try = inchi_min( num_try, pc2i->nNumRemHRevrs-pc2i->nNumRemHInChI);
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_DB_Charged && cur_success < num_try; i ++ ) {
                iat = iat_DB_Charged[i];
                pe   = pBNS->edge + pVA[iat].nCPlusGroupEdge-1;
                if ( pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                for ( j = pv1->num_adj_edges-1; 0 <= j; j -- ) {
                    pe1n = pBNS->edge + pv1->iedge[j];
                    if ( pe1n->flow && !pe1n->forbidden ) {
                        pv1n = pBNS->vert + (v1n = pe1n->neighbor12 ^ v1);
                        break;
                    }
                }
                if ( j < 0 )
                    continue; /* not found */
                
                for ( j = pv2->num_adj_edges-1; 0 <= j; j -- ) { /* was -2; changed 2006-2-28 12:35pm*/
                    pe2n = pBNS->edge + pv2->iedge[j];
                    if ( pe2n->flow && !pe2n->forbidden ) {
                        pv2n = pBNS->vert + (v2n = pe2n->neighbor12 ^ v2);
                        break;
                    }
                }
                if ( j < 0 )
                    continue; /* not found */

                pe->flow   += delta;
                pe1n->flow -= delta;
                pe2n->flow -= delta;
                pv1n->st_edge.flow -= delta;
                pv2n->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1n && vPathStart == v2n) ||
                                  (vPathEnd == v2n && vPathStart == v1n)) &&
                                  (nDeltaCharge == 0 || nDeltaCharge == 1) ) {
                    /* Moved charge from OH(+) to -O- => nDeltaCharge == 1 or 0 if pe2n = -O- charge edge */
                    /* Flow change on pe (+)charge edge (atom OH(+)) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 17 */
                    }
                } else {
                    pe->flow   -= delta;
                    pe1n->flow += delta;
                    pe2n->flow += delta;
                    pv1n->st_edge.flow += delta;
                    pv2n->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( (pc2i->nNumTgInChI && pStruct->endpoint &&
         pc2i->nNumTgMInChI > pc2i->nNumTgMRevrs && pc2i->nNumEndpInChI > pc2i->nNumEndpRevrs ) ) {
        /*-----------------------------------------------------------------*/
        /*                                                                 */
        /* case 18: restored:-N=AB-X                -(-)N-AB-X(+)          */
        /* FixH:              0    0                    0    0             */
        /* MobH:              0    0                    0    0             */
        /*                   non  non                 taut  non            */
        /*                  taut  taut                      taut           */
        /* X = any heteroatom   N=N                                        */
        /* t-group in original has (Hn,-m) in the restored: (Hn,-m+1)      */
        /*       same num_H and more (-) than in the restored structure    */
        /* atom X is not taut in both                                      */
        /* Solution: separate charges between -N(III)= and  X              */
        /*-----------------------------------------------------------------*/
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        int iat, e1, itg, max_success;
        CurrEdges.num_edges = 0;
        cur_success = 0;
        ret = 0;
        /* search for -N= */
        for ( itg = 0; itg < pStruct->ti.num_t_groups && itg < pStruct->One_ti.num_t_groups; itg ++ ) {
            if ( pStruct->ti.t_group[itg].nNumEndpoints <= pStruct->One_ti.t_group[itg].nNumEndpoints ||
                 pStruct->ti.t_group[itg].num[1]  <= pStruct->One_ti.t_group[itg].num[1] ) {
                     continue;
            }
            CurrEdges.num_edges = 0;
            cur_success = 0;
            for ( j = 0, k = pStruct->ti.t_group[itg].nFirstEndpointAtNoPos;
                    j < pStruct->ti.t_group[itg].nNumEndpoints; j ++ ) {
                i = pStruct->ti.nEndpointAtomNumber[k+j]; /* canonical number in restored struct. */
                iat = nCanon2AtnoRevrs[i];
                if ( !pStruct->endpoint[i] || !at_Mobile_H_Revrs || at_Mobile_H_Revrs[iat].endpoint ||
                     pVA[i].cNumValenceElectrons != 5 || pVA[i].cPeriodicRowNumber != 1 ||
                     2 != at2[iat].valence || at2[iat].num_H || at2[iat].radical ||
                     (0 <= (e1=pVA[iat].nCPlusGroupEdge-1) && !pBNS->edge[e1].flow) ||
                     0 > (e=pVA[iat].nCMinusGroupEdge-1) || pBNS->edge[e].forbidden || pBNS->edge[e].flow ) {
                    continue;
                }
                /* found -N= */
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( !(max_success = CurrEdges.num_edges) ) {
            goto exit_case_18;
        }
        /* search for X */
        for ( i = 0; i < pStruct->num_atoms && cur_success < max_success; i ++ ) {
            iat =  nCanon2AtnoRevrs[i];
            if ( pStruct->endpoint[i] || !pVA[i].cNumValenceElectrons || pVA[i].cNumValenceElectrons == 4 ||
                 at2[iat].num_H || at2[iat].radical ||
                 (0 <= (e1=pVA[iat].nCMinusGroupEdge-1) && !pBNS->edge[e1].flow) ||
                 0 > (e=pVA[iat].nCPlusGroupEdge-1) || pBNS->edge[e].forbidden || pBNS->edge[e].flow != 1 ) {
                continue;
            }
            /* try to move the charge */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            SetForbiddenEdgeMask( pBNS, &OtherNFlowerEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask );

            pe   = pBNS->edge + e;
            if ( !pe->flow )
                continue;
            pv1 = pBNS->vert + (v1 = pe->neighbor1);
            pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

            delta = 1;
            pe->flow -= delta;
            pv1->st_edge.flow -= delta;
            pv2->st_edge.flow -= delta;
            pBNS->tot_st_flow -= 2*delta;

            ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                  &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

            if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                              (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                /* Created (-) charge on -N= => nDeltaCharge == 1 */
                /* Flow change on pe (+)charge edge (atom X) is not known to RunBnsTestOnce()) */
                ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                if ( ret > 0 ) {
                    nNumRunBNS ++;
                    cur_success ++; /* 18 */
                }
            } else {
                pe->flow += delta;
                pv1->st_edge.flow += delta;
                pv2->st_edge.flow += delta;
                pBNS->tot_st_flow += 2*delta;
            }
            INCHI_HEAPCHK
        }
exit_case_18:
        RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        RemoveForbiddenEdgeMask( pBNS, &OtherNFlowerEdges, forbidden_edge_mask  );
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( ret < 0 ) {
            goto exit_function;
        }
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }
    if ( pc2i->len_c2at >= 1 ) {
        /*--------------------------------------------------------------*/
        /* case 19 restored:       M--OH   original:  M(-)==OH(+)       */
        /* FixH:               metal  0                      1          */
        /* MobH:                      1                      0          */
        /* O =  O, S, Se, Te; not taut. in InChI                        */
        /* In restored structure has H; tautomeric or not tautomeric    */
        /* Solution: move (+) from -OH to M; charhe on M may vary       */
        /*--------------------------------------------------------------*/
        int iat;
        EdgeIndex eOHPlus, eMPlus, eMMinus, eOMBond;
        BNS_EDGE  *peOHPlus, *peMPlus, *peMMinus, *peOMBond;
        int       iatMetal, ChargeOnMetal, DeltaChargeExpected;
        cur_success = 0;
        num_zero_ret = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: =NH2(+), =OH(+) */
                 (pc2i->c2at[i].nValElectr == 6 ) /* N, O, S, Se, Te */ &&
                 /*!pc2i->c2at[i].endptInChI &&*/ /* <=== relaxation */
                 (e=pVA[iat].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden && pBNS->edge[e].flow &&
                 pc2i->c2at[i].nFixHInChI == 1 && pc2i->c2at[i].nMobHInChI == 0 &&
                 /* reversed structure info: */
                 pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs == 1 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && at2[iat].num_H &&
                 at2[iat].valence == 1 &&
                 at2[iat].valence == at2[iat].chem_bonds_valence &&
                 /* metal atom */
                 pVA[iatMetal=at2[iat].neighbor[0]].cMetal && 
                 (eMPlus=pVA[iatMetal].nCPlusGroupEdge-1) >= 0 && !pBNS->edge[eMPlus].forbidden &&
                 (eMMinus=pVA[iatMetal].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[eMMinus].forbidden &&
                 !pBNS->edge[eOMBond=pBNS->vert[iat].iedge[0]].forbidden
                 ) {

                /* -OH charge edges */
                if ( (ret = AddToEdgeList( &CurrEdges, iat, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( CurrEdges.num_edges ) {
            /* detected; fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            SetForbiddenEdgeMask( pBNS, &NFlowerEdges, forbidden_edge_mask );
            SetForbiddenEdgeMask( pBNS, &AllBondEdges, forbidden_edge_mask );
            for ( i = 0; i < CurrEdges.num_edges; i ++ ) {
                /* v1 is -OH, v2 is adjacent to it Metal */
                iat      = CurrEdges.pnEdges[i];
                iatMetal = at2[iat].neighbor[0];
                peOHPlus = pBNS->edge + (eOHPlus = pVA[iat].nCPlusGroupEdge-1);
                peMPlus  = pBNS->edge + (eMPlus  = pVA[iatMetal].nCPlusGroupEdge-1);
                peMMinus = pBNS->edge + (eMMinus = pVA[iatMetal].nCMinusGroupEdge-1);
                peOMBond = pBNS->edge + (eOMBond =pBNS->vert[iat].iedge[0]);
                /* remove forbidden edge masks */
                peMPlus->forbidden  &= forbidden_edge_mask_inv;
                peMMinus->forbidden &= forbidden_edge_mask_inv;
                peOMBond->forbidden &= forbidden_edge_mask_inv;

                ChargeOnMetal = (peMPlus->cap - peMPlus->flow) - peMMinus->flow;
                if ( 1 == ChargeOnMetal ) {
                    /* We are going to subtract 1 from the charge on Metal */
                    /* Added (+)charge to -OH is not known to RunBnsTestOnce() */
                    DeltaChargeExpected = -1; /* charge will become = 0 */
                } else
                if ( 0 == ChargeOnMetal ) {
                    DeltaChargeExpected = 1; /* charge on Metal will be created */
                } else {
                    DeltaChargeExpected = 0;
                }

                delta = 1;
                pe   = peOHPlus;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->flow -= delta; /* remove (-) from AB-O(-) */
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == DeltaChargeExpected ) {
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 19 */
                    }
                } else {
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
                /* set forbidden edge masks back */
                peMPlus->forbidden  |= forbidden_edge_mask;
                peMMinus->forbidden |= forbidden_edge_mask;
                peOMBond->forbidden |= forbidden_edge_mask;
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &NFlowerEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &AllBondEdges, forbidden_edge_mask );

            CurrEdges.num_edges = 0; /* clear current edge list */
            if ( cur_success ) {
                tot_succes += cur_success;
                /* recalculate InChI from the structure */
                if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                                ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                    goto exit_function;
                }
                if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                    goto exit_function;
                }
                if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                    goto exit_function;  /* no fixed-H found */
                }
                if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                    goto exit_function;
                }
                if ( !pc2i->bHasDifference ) {
                    goto exit_function; /* nothing to do */
                }
            }
        }
    }
    if ( pc2i->len_c2at > 1 && pc2i->nNumTgRevrs && pc2i->nNumTgInChI) {
        /*--------------------------------------------------------------*/
        /* case 20: restored:  O(-)-AB=N-   original:   O=AB-N(-)-      */
        /* FixH:               0       0                0     -1        */
        /* MobH:               0       0                0      1        */
        /*                   taut    non-taut       non-taut taut       */
        /*                           or taut                  no H      */
        /*                           no H                               */
        /* O = O, S, Se; N = N, O, S, Se, Te;                           */
        /* restored atoms are taut/non-taut; original are opposite.     */
        /* Solution: move (-) from O(-) to =N-                          */
        /*--------------------------------------------------------------*/
        int num_SB_O_Minus = 0, num_DB_N = 0, iat;
        short iat_SB_O_Minus[MAX_DIFF_FIXH], iat_DB_N[MAX_DIFF_FIXH];
        
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        /*
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        cur_success = 0;
        CurrEdges.num_edges = 0; /* clear current edge list */
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: =O or -N= */
                 num_DB_N < MAX_DIFF_FIXH &&
                 pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pBNS->edge[e].flow == 0 &&
                 pc2i->c2at[i].nFixHInChI == 0 && pc2i->c2at[i].nMobHInChI == 0 &&
                 /* if  more than 1 t-group are in orig. InChI then do not move (-) to N */
                 (pc2i->nNumTgInChI == 1 || pc2i->c2at[i].nValElectr == 6) &&
                 /* reversed structure info: */
                 !pc2i->c2at[i].endptRevrs &&
                 pc2i->c2at[i].nFixHRevrs ==  0 && /*pc2i->c2at[i].nMobHRevrs == 0 &&*/
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 at2[iat].valence + 1 == at2[iat].chem_bonds_valence ) {
                iat_DB_N[num_DB_N ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            } else
            if ( /* orig. InChI info: -O(-) */
                 num_SB_O_Minus < MAX_DIFF_FIXH &&
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pBNS->edge[e].flow == 1 &&
                 pc2i->c2at[i].nFixHInChI == 0 && pc2i->c2at[i].nMobHInChI == 0 &&
                 pc2i->c2at[i].nValElectr == 6 &&
                 /* reversed structure info: */
                 pc2i->c2at[i].endptRevrs &&
                 pc2i->c2at[i].nFixHRevrs ==  0 && pc2i->c2at[i].nMobHRevrs == 0 &&
                 pc2i->c2at[i].nAtChargeRevrs == -1 && !at2[iat].num_H &&
                 at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 1 ) {
                iat_SB_O_Minus[num_SB_O_Minus ++] = iat;
            }
        }
        if ( !num_DB_N ) {
            /* search among N that are tautomeric in both cases */
            for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
                if ( !pStruct->endpoint[i] ) {
                    continue;
                }
                iat = nCanon2AtnoRevrs[i];
                if ( /* in restored atom O: charge=-1, no H, has no double bond, endpoint */
                     num_DB_N < MAX_DIFF_FIXH &&
                     at2[iat].charge == 0 && !at2[iat].num_H &&
                     at2[iat].valence + 1 == at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                     /* in orig.InChI: an endpoint, has no H */
                     !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                     /*!(nMobHInChI && nMobHInChI[i] ) &&*/
                     /* has (-) edge */
                     (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                     !pBNS->edge[e].flow ) {

                    iat_DB_N[num_DB_N ++] = iat;
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                }
            }
        }
        if ( (num_try = inchi_min( num_SB_O_Minus, num_DB_N )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_O_Minus && cur_success < num_try; i ++ ) {
                iat = iat_SB_O_Minus[i];
                pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Added (-) charge to =N- => nDeltaCharge == 1 */
                    /* Flow change on pe (-)charge edge (atom -O(-)) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 20 */
                    }
                } else {
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }
    if ( pc2i->len_c2at && pc2i->nNumTgRevrs && pc2i->nNumTgHInChI && pStruct->endpoint ) {
        /*--------------------------------------------------------------*/
        /*                      O(-)                      O             */
        /*                      |                         ||            */
        /* case 21: restored: R=S=O         original:   R-S=O           */
        /*                      |                         |             */
        /*                      O(-)                      O(-)          */
        /*                           All O are taut     R is not taut   */
        /*                                                              */
        /* In addition, another atom O that should have been tautomeric */
        /* or has H(+) added in Mobile-H layer is not like that         */
        /* O = O, S, Se;  S=S, Se, Te                                  */
        /* Solution: move (-) from O(-) to =O                           */
        /*           these atoms are tautomeric in restored structure   */
        /*--------------------------------------------------------------*/
        int num_SB_O_Minus = 0, num_DB_O = 0, iat, iS;
        short iat_SB_O_Minus[MAX_DIFF_FIXH], iat_Central[MAX_DIFF_FIXH], iat_DB_O[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        /*
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        CurrEdges.num_edges = 0; /* clear current edge list */
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: =O    */
                 num_DB_O < MAX_DIFF_FIXH &&
                 pc2i->c2at[i].nValElectr == 6 /* O, S, Se, Te */ &&
                 (pc2i->c2at[i].endptInChI || pc2i->c2at[i].nMobHInChI) &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == 0 && /*pc2i->c2at[i].nMobHInChI ==  1 &&*/
                 /* reversed structure info: */
                 !(pc2i->c2at[i].endptRevrs || pc2i->c2at[i].nMobHRevrs) &&
                 pc2i->c2at[i].nFixHRevrs ==  0 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 2 ) {
                iat_DB_O[num_DB_O ++] = iat;
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        for ( i = 0; num_DB_O && i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            if ( !pStruct->endpoint[i] ) {
                continue;
            }
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom O: charge=-1, no H, has no double bond, endpoint */
                 num_SB_O_Minus < MAX_DIFF_FIXH &&
                 at2[iat].charge == -1 && !at2[iat].num_H &&
                 at2[iat].valence == 1 && at2[iat].chem_bonds_valence && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 6 &&
                 (at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint) &&
                 /* in orig.InChI: an endpoint, has no H */
                 !(pStruct->fixed_H && pStruct->fixed_H[i]) &&
                 /*!(nMobHInChI && nMobHInChI[i] ) &&*/
                 /* has (-) edge */
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pBNS->edge[e].flow ) {
                int nNumTautSB = 0, nNumTautDB = 0, nNumOtherDB = 0, nNumOtherSB = 0, nNumOthers = 0, nNumNegEndp = 0;
                /* traverse neighbors of the centerpoint iS */
                iS = at2[i].neighbor[0];
                for ( j = 0; j < num_SB_O_Minus; j ++ ) {
                    if ( iat_Central[j] == iS )
                        break;
                }
                if ( j < num_SB_O_Minus ) {
                    continue;  /* have already been there */
                }
                for ( j = 0; j < at[iS].valence; j ++ ) {
                    int bond_type = at2[iS].bond_type[j];
                    k = at2[iS].neighbor[j];
                    if ( k == i ) {
                        continue;
                    }
                    if ( pStruct->endpoint[k] == pStruct->endpoint[i] ) {
                        nNumTautSB += ( bond_type == BOND_TYPE_SINGLE );
                        nNumTautDB += ( bond_type == BOND_TYPE_DOUBLE );
                    } else
                    if ( bond_type == BOND_TYPE_DOUBLE ) {
                        nNumOtherDB ++;
                    } else
                    if ( bond_type == BOND_TYPE_SINGLE ) {
                        nNumOtherSB ++;
                    } else {
                        nNumOthers ++;
                    }
                    if ( at2[k].endpoint == at2[i].endpoint && at2[k].valence == 1 &&
                         at2[k].charge    == -1 && pVA[k].cNumValenceElectrons == 6 ) {
                        nNumNegEndp ++;
                    }
                }
                if ( !nNumTautSB ) {
                    continue;
                }
                if ( !( nNumOtherDB && nNumTautDB ) ) {
                    continue; /* ignore */
                }
                
                iat_SB_O_Minus[num_SB_O_Minus] = iat;
                iat_Central[num_SB_O_Minus ++] = iS;
            }
        }
        if ( (num_try = inchi_min( num_SB_O_Minus, num_DB_O )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_SB_O_Minus && cur_success < num_try; i ++ ) {
                iat = iat_SB_O_Minus[i];
                pe   = pBNS->edge + pVA[iat].nCMinusGroupEdge-1;
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden |= forbidden_edge_mask;
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Added (-) charge to =O => nDeltaCharge == 1 */
                    /* Flow change on pe (-)charge edge (atom -N(-)-) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 21 */
                    }
                } else {
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at && pc2i->nNumTgRevrs && pc2i->nNumEndpInChI < pc2i->nNumEndpRevrs ) {
        /*--------------------------------------------------------------*/
        /*                      O                         O             */
        /*                      ||                        ||            */
        /* case 21a:restored: R=S-R' =X     original:   R-S-R' -X(-)    */
        /*                      |                         ||            */
        /*                      O(-)                      O(-)          */
        /*             All O and X are taut      O and X are not taut   */
        /*             it is possible that X is R                       */
        /*                                                              */
        /* O = O, S, Se;  S=S, Se, Te; X = N, O, S, Se, Te              */
        /* Solution: move (-) from O(-) to =X                           */
        /*           these atoms are tautomeric in restored structure   */
        /*--------------------------------------------------------------*/
        int iat, iS;
        /*
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        */
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                    pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        /*
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        EDGE_LIST  OtherSO, CentralS, SOMinus, MinusAcceptord;
        CurrEdges.num_edges = 0; /* clear current edge list */
        AllocEdgeList( &OtherSO, EDGE_LIST_CLEAR );
        AllocEdgeList( &CentralS, EDGE_LIST_CLEAR );
        AllocEdgeList( &SOMinus, EDGE_LIST_CLEAR );
        AllocEdgeList( &MinusAcceptord, EDGE_LIST_CLEAR );
        cur_success = 0;
        if ( !at_Mobile_H_Revrs ) {
            goto exit_case_21a;
        }
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: -X(-)    */
                 /*num_DB_O < MAX_DIFF_FIXH &&*/
                 /*pc2i->c2at[i].nValElectr == 6 */ /* O, S, Se, Te */
                 !pc2i->c2at[i].endptInChI &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == 0 && /*pc2i->c2at[i].nMobHInChI ==  1 &&*/
                 /* reversed structure info: */
                 (pc2i->c2at[i].endptRevrs || pc2i->c2at[i].nMobHRevrs) &&
                 pc2i->c2at[i].nFixHRevrs ==  0 &&
                 /*pc2i->c2at[i].nAtChargeRevrs == 0 &&*/ !at2[iat].num_H ) {
                if ( pVA[iat].cNumValenceElectrons == 6 && at2[iat].charge == -1 &&
                     pBNS->edge[e].flow &&
                     at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 1 &&
                     pVA[iS=(int)at2[iat].neighbor[0]].cNumValenceElectrons == 6 && pVA[iS].cPeriodicRowNumber > 1 &&
                     at2[iS].valence >= 4 ) {
                    /* a candidate for S in -SO2- */
                    int nNumTautSB = 0, nNumTautDB = 0, nNumOtherDB = 0, nNumOtherSB = 0;
                    int nNumOthers = 0, nNumNegEndp = 0, nNumEndpO = 0;
                    /* check whether we have already found it */
                    if ( 0 <= FindInEdgeList( &CentralS, iS ) ) {
                        continue;
                    }
                    for ( j = 0; j < at[iS].valence; j ++ ) {
                        int bond_type = at2[iS].bond_type[j];
                        k = at2[iS].neighbor[j];
                        if ( k == iat ) {
                            continue;
                        }
                        if ( pc2i->c2at[i].endptRevrs == at_Mobile_H_Revrs[k].endpoint && !at2[k].endpoint ) {
                            nNumTautSB += ( bond_type == BOND_TYPE_SINGLE );
                            nNumTautDB += ( bond_type == BOND_TYPE_DOUBLE );
                            nNumEndpO  += (pVA[k].cNumValenceElectrons == 6 && at2[k].valence == 1);
                        } else
                        if ( bond_type == BOND_TYPE_DOUBLE ) {
                            nNumOtherDB ++;
                        } else
                        if ( bond_type == BOND_TYPE_SINGLE ) {
                            nNumOtherSB ++;
                        } else {
                            nNumOthers ++;
                        }
                        if ( at2[k].endpoint == at2[i].endpoint && at2[k].valence == 1 &&
                             at2[k].charge    == -1 && pVA[k].cNumValenceElectrons == 6 ) {
                            nNumNegEndp ++;
                        }
                    }
                    if ( !nNumEndpO ) {
                        continue;
                    }
                    if ( nNumTautSB + nNumTautDB + nNumOtherDB <= nNumEndpO  ) {
                        continue; /* ignore */
                    }
                    /* collect double bond taut =O */
                    for ( j = 0; j < at[iS].valence; j ++ ) {
                        int bond_type = at2[iS].bond_type[j];
                        k = at2[iS].neighbor[j];
                        if ( pc2i->c2at[i].endptRevrs == at_Mobile_H_Revrs[k].endpoint &&
                             !at2[k].endpoint && pVA[k].cNumValenceElectrons == 6 && at2[k].valence == 1 &&
                             0 <= (e=pVA[k].nCMinusGroupEdge-1) && !pBNS->edge[e].forbidden ) {
                            if ( bond_type == BOND_TYPE_DOUBLE && !at2[k].charge && !pBNS->edge[e].flow) {
                                /* charges to be unchanged */
                                if ( (ret = AddToEdgeList( &OtherSO, e, INC_ADD_EDGE )) ) {
                                    goto exit_case_21a;
                                }
                            } else
                            if ( bond_type == BOND_TYPE_SINGLE && at2[k].charge == -1 && pBNS->edge[e].flow ) {
                                /* charges to be removed */
                                if ( (ret = AddToEdgeList( &SOMinus, e, INC_ADD_EDGE )) ) {
                                    goto exit_case_21a;
                                }
                            }
                        }
                    }
                    if ( (ret = AddToEdgeList( &CentralS, iS, INC_ADD_EDGE )) ) {
                        goto exit_case_21a;
                    }
                } else
                if ( at2[iat].charge == 0 && !pBNS->edge[e].flow &&
                     at2[iat].valence + 1 == at2[iat].chem_bonds_valence ) {
                    /* changeable charges */
                    if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                        goto exit_function;
                    }
                }
            }
        }
        /* remove unchangeable from changeable */
        for ( i = 0; i < OtherSO.num_edges; i ++ ) {
            RemoveFromEdgeListByValue( &CurrEdges, OtherSO.pnEdges[i] );
        }

        if ( (num_try = inchi_min( SOMinus.num_edges, CurrEdges.num_edges )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < SOMinus.num_edges && cur_success < num_try; i ++ ) {
                pe   = pBNS->edge + SOMinus.pnEdges[i];
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                /*pe->forbidden |= forbidden_edge_mask;*/
                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 1 ) {
                    /* Added (-) charge to =O => nDeltaCharge == 1 */
                    /* Flow change on pe (-)charge edge (atom -N(-)-) is not known to RunBnsTestOnce()) */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 21a */
                    }
                } else {
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
exit_case_21a:
        CurrEdges.num_edges = 0; /* clear current edge list */
        AllocEdgeList( &OtherSO, EDGE_LIST_FREE );
        AllocEdgeList( &CentralS, EDGE_LIST_FREE );
        AllocEdgeList( &SOMinus, EDGE_LIST_FREE );
        AllocEdgeList( &MinusAcceptord, EDGE_LIST_FREE );
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }

    if ( pc2i->len_c2at ) {
        /*------------------------------------------------------------------*/
        /* case 22: restored: N(-)=N(+)=C...=O orig: N#N-N=...-O(-)         */
        /*     im InChI        -O(-) may have H(+) added by Normalization   */
        /*                           or may be tautomeric                   */
        /* Solution: move (-) from N(-) to =O                               */
        /*                                                                  */
        /*------------------------------------------------------------------*/
        int num_DB_O = 0, iat;
        short iat_DB_O[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        int iN2, iC;
        BNS_EDGE *peDB_O_Minus;
        /*
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        CurrEdges.num_edges = 0; /* clear current edge list */
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: =O    */
                 num_DB_O < MAX_DIFF_FIXH &&
                 pc2i->c2at[i].nValElectr == 6 /* O, S, Se, Te */ &&
                 (pc2i->c2at[i].endptInChI || pc2i->c2at[i].nMobHInChI) &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == 0 && /*pc2i->c2at[i].nMobHInChI ==  1 &&*/
                 /* reversed structure info: */
                 !(pc2i->c2at[i].endptRevrs || pc2i->c2at[i].nMobHRevrs) &&
                 pc2i->c2at[i].nFixHRevrs ==  0 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 2 ) {
                iat_DB_O[num_DB_O ++] = iat;
            }
        }
        for ( i = 0; num_DB_O && i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            iat = nCanon2AtnoRevrs[i];
            if ( /* in restored atom O: charge=-1, no H, has no double bond, endpoint */
                 at2[iat].charge == -1 && !at2[iat].num_H &&
                 at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 2 && !pVA[iat].cMetal &&
                 pVA[iat].cNumValenceElectrons == 5 &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pBNS->edge[e].flow &&
                 !(at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint) &&
                 pVA[iN2=at2[iat].neighbor[0]].cNumValenceElectrons == 5 &&
                 at2[iat].bond_type[0] == BOND_TYPE_DOUBLE &&
                 at2[iN2].charge == 1 && at2[iN2].valence == 2 && at2[iN2].chem_bonds_valence == 4 &&
                 pVA[iC=at2[iN2].neighbor[at2[iN2].neighbor[0]==iN2]].cNumValenceElectrons == 4 ) {
                
                if ( (ret = AddToEdgeList( &CurrEdges, e, INC_ADD_EDGE )) ) {
                    goto exit_function;
                }
            }
        }
        if ( (num_try = inchi_min( CurrEdges.num_edges, num_DB_O )) ) {
            /* detected; attempt to fix */
            SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
            RemoveForbiddenEdgeMask( pBNS, &CurrEdges, forbidden_edge_mask  );
            delta = 1;
            for ( i = 0; i < num_DB_O && cur_success < num_try; i ++ ) {
                iat = iat_DB_O[i];

                peDB_O_Minus = pBNS->edge + (pVA[iat].nCMinusGroupEdge-1);
                pe           = pBNS->edge + pBNS->vert[iat].iedge[0];
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden            |= forbidden_edge_mask;
                peDB_O_Minus->forbidden  &= forbidden_edge_mask_inv;

                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) && nDeltaCharge == 0 ) {
                    /* Added (-) charge to =O and removed from =N(-) => nDeltaCharge == 0 */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        cur_success ++; /* 22 */
                    }
                } else {
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
                INCHI_HEAPCHK
                pe->forbidden            &= forbidden_edge_mask_inv;
                peDB_O_Minus->forbidden  |= forbidden_edge_mask;
            }
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask  );
        }
        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
    }
    if ( pc2i->len_c2at && pc2i->nNumTgInChI == 1 ) {
        /*------------------------------------------------------------------*/
        /* case 23: -NO2 are to be tautomeric but they are not AND          */
        /*          InChI has a SINGLE tautomeric group                     */
        /*                                                                  */
        /*                   (-)O                   (-)O                    */
        /* Solution: convert     \                      \                   */
        /*                        N-X=...-Z(-)   =>      N(+)=X- ...=Z      */
        /*                      //                      /                   */
        /*                     O                    (-)O                    */
        /*                                                                  */
        /*                     O                       O                    */
        /*        or            \\                      \\                  */
        /*                        N-X=...-Z(-)    =>      N=X-  ...=Z       */
        /*                      //                       /                  */
        /*                     O                     (-)O                   */
        /*                                                                  */
        /*                                                                  */
        /*  (a) move (-) from other tautomeric atom to O in O=N-X           */
        /*          or   from other atom that has to be tautomeric          */
        /*               but is not                                         */
        /*  (b) create (+) [ion pair creation] on N as in                   */
        /*                                                                  */
        /*       OH             OH                                          */
        /*      /              /                                            */
        /*  -C=N     =>  =C-N(+)                                            */
        /*     \\             \\                                            */
        /*       O              O                                           */
        /*                                                                  */
        /*------------------------------------------------------------------*/
        int num_DB_O = 0, iat;
        short iat_DB_O[MAX_DIFF_FIXH], iat_NO2[MAX_DIFF_FIXH];
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        /*
        inp_ATOM *atfMobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at_fixed_bonds)?
                             pStruct->pOne_norm_data[1]->at_fixed_bonds : NULL;
        */
        S_CHAR   *num_Fixed_H_Revrs = pStruct->pOneINChI[0]->nNum_H_fixed? pStruct->pOneINChI[0]->nNum_H_fixed : NULL;
        S_CHAR   *pnMobHRevrs = (pStruct->pOneINChI[1] && pStruct->pOneINChI[1]->nNum_H)?
                               pStruct->pOneINChI[1]->nNum_H : 
                            (pStruct->pOneINChI[0] && pStruct->pOneINChI[0]->nNum_H)?
                               pStruct->pOneINChI[0]->nNum_H : NULL;
        int iN, one_success;
        BNS_EDGE *peDB_O_Minus;
        int neigh, nNumO, nNumOthers;
#define CHG_SET_NOOH         0
#define CHG_SET_WRONG_TAUT   1
#define CHG_SET_TAUT         2
#define CHG_LAST_SET         2 /* the last index in trying */
#define CHG_SET_O_FIXED      3
#define CHG_SET_NUM          4
        EDGE_LIST ChangeableEdges[CHG_SET_NUM];
        memset( ChangeableEdges, 0, sizeof(ChangeableEdges) );
        /* equivalent to AllocEdgeList( &EdgeList, EDGE_LIST_CLEAR ); */
        /*
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        CurrEdges.num_edges = 0; /* clear current edge list */
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: taut in orig. InChI =O located in -NO2 that is not taut in Reconstructed InChI */
                 num_DB_O < MAX_DIFF_FIXH &&
                 pc2i->c2at[i].nValElectr == 6 /* O, S, Se, Te */ &&
                 (pc2i->c2at[i].endptInChI /*|| pc2i->c2at[i].nMobHInChI*/) &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == 0 && /*pc2i->c2at[i].nMobHInChI ==  1 &&*/
                 /* reversed structure info: */
                 !(pc2i->c2at[i].endptRevrs /*|| pc2i->c2at[i].nMobHRevrs*/) &&
                 pc2i->c2at[i].nFixHRevrs ==  0 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 at2[iat].valence == 1 && at2[iat].chem_bonds_valence == 2 &&
                 /* find whether it belongs to NO2 */
                 pVA[iN=at2[iat].neighbor[0]].cNumValenceElectrons == 5 &&
                 at2[iN].valence == 3 && (at2[iN].charge == 0 || at2[iN].charge == 1) &&
                 at2[iN].chem_bonds_valence == 5 - at2[iN].charge ) {
                /* find the second O */
                nNumO = nNumOthers = 0;
                for ( k = 0; k < at2[iN].valence; k ++ ) {
                    neigh = at2[iN].neighbor[k];
                    if ( neigh == iat ) {
                        continue;
                    }
                    if ( pVA[neigh].cNumValenceElectrons == 6 &&
                         pStruct->endpoint[neigh] &&
                         !(at_Mobile_H_Revrs && at_Mobile_H_Revrs[neigh].endpoint) &&
                         at2[neigh].valence == 1 && at2[neigh].num_H == 0 &&
                         at2[neigh].radical == 0 && (at2[neigh].charge == 0 || at2[neigh].charge == -1) &&
                         at2[neigh].chem_bonds_valence - at2[neigh].charge == 2) {
                        nNumO ++;
                    } else
                    if ( at2[iN].bond_type[k] == BOND_TYPE_SINGLE &&
                         at2[neigh].valence > 1 &&
                         at2[neigh].valence < at2[neigh].chem_bonds_valence ) {
                        nNumOthers ++;
                    }
                }
                if ( nNumO != 1 || nNumOthers != 1 ) {
                    continue;
                }
                for ( k = 0; k < num_DB_O; k ++ ) {
                    if ( iat_NO2[k] == iN ) {
                        break;
                    }
                }
                if ( k == num_DB_O ) {
                    iat_NO2[num_DB_O]     = iN;
                    iat_DB_O[num_DB_O ++] = iat;
                }
                /* save the edge to avoid interference */
                if ( (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_O_FIXED], e, INC_ADD_EDGE )) ) {
                    goto exit_case_23;
                }
            }
        }
        if ( num_DB_O ) {
            /* 1. search for =N(=O)-OH; assume =N(+)(-O(-))(-OH) does not happen */
            for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
                /* find O=N(V) */
                iat = nCanon2AtnoRevrs[i];
                if ( !pStruct->endpoint[i] || pVA[i].cNumValenceElectrons != 6 ||
                     at2[iat].valence != 1 || at2[iat].charge ||
                     0 > (e = pVA[iat].nCMinusGroupEdge-1) ||
                     at2[iat].num_H + at2[iat].chem_bonds_valence != 2 ||
                     pVA[iN=at2[iat].neighbor[0]].cNumValenceElectrons != 5 ||
                     0 > (e = pVA[iN].nCPlusGroupEdge-1) ||
                     pBNS->edge[e].forbidden || !pBNS->edge[e].flow ||
                     at2[iN].charge || at2[iN].valence != 3 || at2[iN].chem_bonds_valence != 5) {
                    continue;
                }
                /* find the second O, -OH */
                nNumO = nNumOthers = 0;
                for ( k = 0; k < at2[iN].valence; k ++ ) {
                    neigh = at2[iN].neighbor[k];
                    if ( neigh == iat ) {
                        continue;
                    }
                    if ( pVA[neigh].cNumValenceElectrons == 6 &&
                         pStruct->endpoint[neigh] &&
                         at2[neigh].valence == 1 && at2[neigh].num_H == 1 &&
                         at2[neigh].radical == 0 && (at2[neigh].charge == 0 ) ) {
                        nNumO ++;
                    } else
                    if ( at2[iN].bond_type[k] == BOND_TYPE_DOUBLE &&
                         at2[neigh].valence >= 2 &&
                         at2[neigh].valence < at2[neigh].chem_bonds_valence ) {
                        nNumOthers ++;
                    }
                }
                if ( nNumO != 1 || nNumOthers != 1 ) {
                    continue;
                }
                /* save edges to be changed */
                if ( (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NOOH], e, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_O_FIXED], e, INC_ADD_EDGE ))) {
                    goto exit_case_23;
                }
                if ( NO_VERTEX != (j = GetChargeFlowerUpperEdge( pBNS, pVA, e )) &&
                     (( ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NOOH], j, INC_ADD_EDGE ) ) ||
                      ( ret = AddToEdgeList( &ChangeableEdges[CHG_SET_O_FIXED], e, INC_ADD_EDGE ) ))) {
                    goto exit_case_23;
                }
            }
            /* 2. search for (-) atoms that are tautomeric but should not be  */
            /*           or that got H from Normalization but they shouldn't  */
            for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
                iat = nCanon2AtnoRevrs[i];
                if ( at2[iat].charge == -1 &&
                     !pStruct->endpoint[i] &&
                     (at_Mobile_H_Revrs && 
                     (at_Mobile_H_Revrs[i].endpoint || at2[iat].num_H < at_Mobile_H_Revrs[i].num_H )) )  {

                    if ( 0 <= (e = pVA[iat].nCMinusGroupEdge-1) &&
                         0 > FindInEdgeList( &ChangeableEdges[CHG_SET_O_FIXED], e ) &&
                         !pBNS->edge[e].forbidden && pBNS->edge[e].flow &&
                         (
                          ( ret = AddToEdgeList( &ChangeableEdges[CHG_SET_WRONG_TAUT], e, INC_ADD_EDGE ) ) ||
                          ( ret = AddToEdgeList( &ChangeableEdges[CHG_SET_O_FIXED], e, INC_ADD_EDGE ) )
                         ) ) {
                        goto exit_case_23;
                    }
                } else
                /* negatively charged atom in Reconstructed structure got H(+) from Normalization */
                /* and is not tautomeric; in the original structure it is tautomeric */    
                if ( at2[iat].charge == -1 &&
                     pStruct->endpoint[i] &&
                     !(at_Mobile_H_Revrs && at_Mobile_H_Revrs[i].endpoint) &&
                     (num_Fixed_H_Revrs && num_Fixed_H_Revrs[i] == -1) &&
                     (pnMobHRevrs       && pnMobHRevrs[i]       ==  1) && 
                     pStruct->fixed_H[i] == 0 ) {

                    if ( 0 <= (e = pVA[iat].nCMinusGroupEdge-1) &&
                         0 > FindInEdgeList( &ChangeableEdges[CHG_SET_O_FIXED], e ) &&
                         !pBNS->edge[e].forbidden && pBNS->edge[e].flow &&
                         (
                          ( ret = AddToEdgeList( &ChangeableEdges[CHG_SET_WRONG_TAUT], e, INC_ADD_EDGE ) ) ||
                          ( ret = AddToEdgeList( &ChangeableEdges[CHG_SET_O_FIXED], e, INC_ADD_EDGE ) )
                         ) ) {
                        goto exit_case_23;
                    }
                }
            }
            /* 3. Search for (-) atoms that are tautomeric */
            for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
                iat = nCanon2AtnoRevrs[i];
                if ( pStruct->endpoint[i] &&
                     (at_Mobile_H_Revrs && at_Mobile_H_Revrs[i].endpoint) &&
                     at2[iat].charge == -1
                    /*&& pVA[i].cNumValenceElectrons == 6*/ ) {
                    if ( 0 <= (e = pVA[iat].nCMinusGroupEdge-1) &&
                         !pBNS->edge[e].forbidden && pBNS->edge[e].flow &&
                         0 > FindInEdgeList( &ChangeableEdges[CHG_SET_O_FIXED], e )  &&
                         ( ret = AddToEdgeList( &ChangeableEdges[CHG_SET_TAUT], e, INC_ADD_EDGE ) ) ) {
                        goto exit_case_23;
                    }
                }
            }
            /* ------- finally, try to move charges from O=N --------------*/
            for ( i = 0; i < num_DB_O; i ++ ) {
                int nDeltaChargeExpected;
                one_success = 0;
                delta = 1;
                iat = iat_DB_O[i];
                peDB_O_Minus = pBNS->edge + (pVA[iat].nCMinusGroupEdge-1);
                pe =           pBNS->edge + pBNS->vert[iat].iedge[0];
                
                if ( !pe->flow )
                    continue;
                pv1 = pBNS->vert + (v1 = pe->neighbor1);
                pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

                pe->forbidden            |= forbidden_edge_mask;

                pe->flow -= delta;
                pv1->st_edge.flow -= delta;
                pv2->st_edge.flow -= delta;
                pBNS->tot_st_flow -= 2*delta;

                for ( k = 0; !one_success && k <= CHG_LAST_SET; k ++ ) {
                    if ( !ChangeableEdges[k].num_edges ) {
                        continue;
                    }
                    nDeltaChargeExpected = (k==CHG_SET_NOOH)? 2 : 0;
                    
                    SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                    RemoveForbiddenEdgeMask( pBNS, &ChangeableEdges[k], forbidden_edge_mask  );
                    /* allow (-) charge to move to N=O */
                    peDB_O_Minus->forbidden  &= forbidden_edge_mask_inv;
                    
                    ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                          &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                    if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                      (vPathEnd == v2 && vPathStart == v1)) &&
                                      nDeltaCharge == nDeltaChargeExpected ) {
                        /* Move (-) charge to =O and remove it an endpoint => nDeltaCharge == 0 */
                        ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                        if ( ret > 0 ) {
                            nNumRunBNS ++;
                            one_success ++; /* 23 */
                        }
                    }
                    INCHI_HEAPCHK
                }
                cur_success += one_success;
                
                RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                pe->forbidden            &= forbidden_edge_mask_inv;

                if ( !one_success ) {
                    pe->flow += delta;
                    pv1->st_edge.flow += delta;
                    pv2->st_edge.flow += delta;
                    pBNS->tot_st_flow += 2*delta;
                }
            }
        }
exit_case_23:
        for ( i = 0; i < CHG_SET_NUM; i ++ ) {
            AllocEdgeList( &ChangeableEdges[i], EDGE_LIST_FREE );
        }

        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
#undef CHG_SET_NOOH
#undef CHG_SET_WRONG_TAUT
#undef CHG_SET_TAUT
#undef CHG_LAST_SET
#undef CHG_SET_O_FIXED
#undef CHG_SET_NUM
    }

    if ( pc2i->len_c2at && pc2i->nNumTgInChI == 1 ) {
        /*------------------------------------------------------------------*/
        /* case 24: InChI norm. -N(-)-N(+)(IV) => -N=N(V) prevents tauto-   */
        /*          merism on -N(-)- in case of ADP                         */
        /*                                                                  */
        /* Solution: convert       N(V)=N-   ...=X    -> N(IV)(+)-N=...-X(-)*/
        /*                     N(IV)(+)-N(-)-...=X                          */
        /*                                                                  */
        /*      Orig InChI            taut      taut, 1 t-group only(ADP?)  */
        /*   Reconstructed struct   non-taut    possibly not taut           */
        /*                                                                  */
        /*   Details: 1a. store next to N(V) (+)edge its flower edge        */
        /*            1b. store next to N(-) edge NO_VERTEX                 */
        /*            2.  Release (-) edges of other missing endpoints or   */
        /*                all endpoints if no other is missing              */
        /*            3.  Decrement flow on (+) edge                        */
        /*                if flower edge is stored then expect DeltaCharge=2*/
        /*                otherwise DeltaCharge = 0                         */
        /*------------------------------------------------------------------*/
        int iat;
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        inp_ATOM *atf  = (pStruct->pOne_norm_data[1] && pStruct->pOne_norm_data[1]->at_fixed_bonds)?
                            pStruct->pOne_norm_data[1]->at_fixed_bonds : NULL;
        int iN, one_success;
        EdgeIndex  ef, e1;
        BNS_EDGE *pef;
#define CHG_SET_MISSED_TAUT   0
#define CHG_SET_OTHER_TAUT_O  1
#define CHG_SET_OTHER_TAUT_N  2
#define CHG_LAST_SET          2 /* the last index in trying */
#define CHG_SET_NN            3
#define CHG_SET_AVOID         4
#define CHG_SET_NUM           5
        EDGE_LIST ChangeableEdges[CHG_SET_NUM];
        memset( ChangeableEdges, 0, sizeof(ChangeableEdges) );
        /* equivalent to AllocEdgeList( &EdgeList, EDGE_LIST_CLEAR ); */
        /*
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        CurrEdges.num_edges = 0; /* clear current edge list */
        cur_success = 0;
        for ( i = 0; i < pc2i->len_c2at; i ++ ) {
            iat = pc2i->c2at[i].atomNumber;
            if ( /* orig. InChI info: -N=N(V)    */
                 pc2i->c2at[i].nValElectr == 5 /* N or P */ &&
                 (pc2i->c2at[i].endptInChI /* only N */) &&
                 (e1=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e1].forbidden &&
                 pc2i->c2at[i].nFixHInChI == 0 && pc2i->c2at[i].nMobHInChI == 0 &&
                 /* reversed structure info: */
                 !pc2i->c2at[i].endptRevrs &&
                 pc2i->c2at[i].nFixHRevrs ==  0 &&
                 pc2i->c2at[i].nAtChargeRevrs == 0 && !at2[iat].num_H &&
                 at2[iat].valence == 2 && at2[iat].chem_bonds_valence == 3 &&
                 /* find whether -N= has =N(V) neighbor; Note: operator comma: (A,B) returns B */
                 (iN = at2[iat].neighbor[at2[iat].bond_type[0] != BOND_TYPE_DOUBLE],
                  pVA[iN].cNumValenceElectrons == 5) &&
                 at2[iN].chem_bonds_valence == 5  && 
                 at2[iN].charge == 0 && !at2[iN].num_H && !at2[iN].radical &&
                 0 <= (e=pVA[iN].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden && pBNS->edge[e].flow &&
                 0 > FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e )) {

                ef = GetChargeFlowerUpperEdge( pBNS, pVA, e ); /* == NO_VERTEX if N(V) has 4 bonds */
                if ( (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NN], e, INC_ADD_EDGE ))    ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NN], ef, INC_ADD_EDGE ))   ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NN], 1, INC_ADD_EDGE ))    || /* expected nDeltaCharge */
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e1, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], ef, INC_ADD_EDGE ))) {
                    goto exit_case_24;
                }
                /* mark -N= so that (-) will not be moved to it */
                if ( 0 <= (e = pVA[iat].nCMinusGroupEdge) && !pBNS->edge[e].forbidden &&
                     0 > FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e ) &&
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e, INC_ADD_EDGE ))) {
                    goto exit_case_24;
                }
            } else
            if ( /* orig. InChI info: -N(-)N(IV)(+)    */
                 atf &&
                 pc2i->c2at[i].nValElectr == 5 /* N or P */ &&
                 pc2i->c2at[i].endptInChI /* only N */ &&
                 (e=pVA[iat].nCMinusGroupEdge-1) >= 0 && !pBNS->edge[e].forbidden &&
                 pc2i->c2at[i].nFixHInChI == 0 && pc2i->c2at[i].nMobHInChI == 0 &&
                 /* reversed structure info: */
                 !pc2i->c2at[i].endptRevrs &&
                 pc2i->c2at[i].nFixHRevrs ==  0 &&
                 pc2i->c2at[i].nAtChargeRevrs == -1 && !at2[iat].num_H &&
                 at2[iat].valence == 2 && at2[iat].chem_bonds_valence == 2 &&
                 atf[iat].valence == 2 && atf[iat].chem_bonds_valence == 3 && 
                 /* find whether -N= has =N(V) neighbor; Note: operator comma: (A,B) returns B */
                 (iN=atf[iat].neighbor[atf[iat].bond_type[0] != BOND_TYPE_DOUBLE],
                  pVA[iN].cNumValenceElectrons == 5) &&
                 at2[iN].charge == 1 && /* double bond neighbor */
                 at2[iN].chem_bonds_valence == 4 &&
                 atf[iN].charge == 0 &&
                 atf[iN].chem_bonds_valence == 5  &&  /* InChI normalization created N(V)=N- out of N(IV)(+)-N(-)- */
                 !at2[iN].num_H && !at2[iN].radical &&
                 0 <= (e=pVA[iat].nCMinusGroupEdge-1) && !pBNS->edge[e].forbidden && pBNS->edge[e].flow &&
                 0 > FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e ) ) {
                /* save (-) edge */
                if ( (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NN], e, INC_ADD_EDGE ))    ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NN], NO_VERTEX, INC_ADD_EDGE ))   ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NN], 1, INC_ADD_EDGE ))   || /* expected nDeltaCharge */
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e, INC_ADD_EDGE ))) {
                    goto exit_case_24;
                }
            }
        }
        if ( !ChangeableEdges[CHG_SET_NN].num_edges ) {
            goto  exit_case_24;
        }
        /* Collect all relevant tautomeric atoms */
        for ( i = 0; i < pStruct->num_atoms; i ++ ) { /* i = canonical number - 1 */
            if ( !pStruct->endpoint[i] ) {
                continue;
            }
            iat = nCanon2AtnoRevrs[i];
            if ( at2[iat].charge || at2[iat].radical || at2[iat].valence == at2[iat].chem_bonds_valence ) {
                continue; /* cannot be an acceptor of (-) */
            }
            if ( 0 > (e=pVA[iat].nCMinusGroupEdge-1) || pBNS->edge[e].forbidden || pBNS->edge[e].flow ) {
                continue;
            }
            if ( 0 <= FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e ) ) {
                continue; /* has already been used */
            }
            /* missing endpoint */ 
            if ( !(at_Mobile_H_Revrs && at_Mobile_H_Revrs[iat].endpoint) ) {
                if ( 0 > FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e ) && (
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_MISSED_TAUT], e, INC_ADD_EDGE ))   ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e, INC_ADD_EDGE )))) {
                    goto exit_case_24;
                }
            } else
            /* endpoint O */
            if ( pVA[iat].cNumValenceElectrons == 6 ) {
                 if ( 0 > FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e ) && (
                      (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_OTHER_TAUT_O], e, INC_ADD_EDGE ))   ||
                      (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e, INC_ADD_EDGE )))){
                    goto exit_case_24;
                 }
            } else
            /* endpoint N */
            if ( pVA[iat].cNumValenceElectrons == 5 ) {
                if ( 0 > FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e ) && ( 
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_OTHER_TAUT_N], e, INC_ADD_EDGE ))   ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e, INC_ADD_EDGE )))){
                    goto exit_case_24;
                }
            }
        }
        /* ------- finally, try to move charges from -N(-)-N(+) or to N(V) --------------*/
        for ( i = 0; i < ChangeableEdges[CHG_SET_NN].num_edges; i += 3 ) {
            int nDeltaChargeExpected;
            one_success = 0;
            delta = 1;
            pe  = pBNS->edge + ChangeableEdges[CHG_SET_NN].pnEdges[i];
            pef = (NO_VERTEX != ChangeableEdges[CHG_SET_NN].pnEdges[i+1])?
                  pBNS->edge + ChangeableEdges[CHG_SET_NN].pnEdges[i+1] : NULL;
            nDeltaChargeExpected = ChangeableEdges[CHG_SET_NN].pnEdges[i+2];

            if ( !pe->flow )
                continue;
            pv1 = pBNS->vert + (v1 = pe->neighbor1);
            pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

            pe->flow -= delta;
            pv1->st_edge.flow -= delta;
            pv2->st_edge.flow -= delta;
            pBNS->tot_st_flow -= 2*delta;

            for ( k = 0; !one_success && k <= CHG_LAST_SET; k ++ ) {
                if ( !ChangeableEdges[k].num_edges ) {
                    continue;
                }
                SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                RemoveForbiddenEdgeMask( pBNS, &ChangeableEdges[k], forbidden_edge_mask  );
                /* allow change of N(V) flower edge */
                if ( pef ) {
                    pef->forbidden  &= forbidden_edge_mask_inv;
                }
                
                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) &&
                                  nDeltaCharge == nDeltaChargeExpected ) {
                    /* Move (-) charge to =O and remove it an endpoint => nDeltaCharge == 0 */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        one_success ++; /* 24 */
                    }
                }
                INCHI_HEAPCHK
            }
            cur_success += one_success;
            
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );

            if ( !one_success ) {
                pe->flow += delta;
                pv1->st_edge.flow += delta;
                pv2->st_edge.flow += delta;
                pBNS->tot_st_flow += 2*delta;
            }
        }
exit_case_24:
        for ( i = 0; i < CHG_SET_NUM; i ++ ) {
            AllocEdgeList( &ChangeableEdges[i], EDGE_LIST_FREE );
        }

        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
#undef CHG_SET_NN
#undef CHG_SET_MISSED_TAUT
#undef CHG_SET_OTHER_TAUT_O
#undef CHG_SET_OTHER_TAUT_N
#undef CHG_LAST_SET
#undef CHG_SET_AVOID
#undef CHG_SET_NUM
    }

    /* pStruct->nNumRemovedProtonsMobHInChI == pc2i->nNumRemHInChI */

    if ( pc2i->len_c2at && pc2i->nNumTgInChI == 1 &&
         pc2i->nNumRemHRevrs > pc2i->nNumRemHInChI && 0 > pc2i->nNumRemHInChI &&
         (pc2i->nNumEndpRevrs < pc2i->nNumEndpInChI ||
          pc2i->nNumTgRevrs > pc2i->nNumTgInChI ) ) {
        /*------------------------------------------------------------------*/
        /* case 25: Restored InChI does not have 2 or more added protons    */
        /*                         possibly taut. endpoints are missing     */
        /*                         has -N(-O(-))-O(-) group(s)              */
        /*          Original InChI has only one t-group                     */
        /*                                                                  */
        /* Solution: convert       -N(-O(-))-O(-) -> -N(+)(=O)-O(-)         */
        /*                         and direct 2(-) to the missing taut atoms*/
        /*           at first attempt try to move (-) to N only             */
        /*                                                                  */
        /*------------------------------------------------------------------*/
        int iat;
        AT_NUMB  *nCanon2AtnoRevrs = pStruct->nCanon2Atno[0];
        AT_NUMB  *nAtno2CanonRevrs = pStruct->nAtno2Canon[0];
        inp_ATOM *at_Mobile_H_Revrs = (pStruct->pOne_norm_data[1] &&
                             pStruct->pOne_norm_data[1]->at)? pStruct->pOne_norm_data[1]->at : NULL;
        /*
        inp_ATOM *atf  = (pStruct->pOne_norm_data[1] && pStruct->pOne_norm_data[1]->at_fixed_bonds)?
                            pStruct->pOne_norm_data[1]->at_fixed_bonds : NULL;
        */
        int iN, neigh, one_success;
        EdgeIndex  e1, bFirst;
        BNS_EDGE *pef;
#define CHG_SET_MISSED_TAUT_1   0
#define CHG_SET_MISSED_TAUT_ALL 1
#define CHG_SET_OTHER_TAUT_1    2
#define CHG_SET_OTHER_TAUT_ALL  3
#define CHG_LAST_SET            3 /* the last index in trying */
#define CHG_SET_NO_IN_NO2M2     4
#define CHG_SET_AVOID           5
#define CHG_SET_NUM             6
        EDGE_LIST ChangeableEdges[CHG_SET_NUM];
        memset( ChangeableEdges, 0, sizeof(ChangeableEdges) );
        /* equivalent to AllocEdgeList( &EdgeList, EDGE_LIST_CLEAR ); */
        /*
        S_CHAR   *nMobHInChI = pInChI[1] && pInChI[1]->nNum_H? pInChI[1]->nNum_H :
                               pInChI[0] && pInChI[0]->nNum_H? pInChI[0]->nNum_H : 0;
        */
        CurrEdges.num_edges = 0; /* clear current edge list */
        cur_success = 0;
        /* find all -N(-O(-))-O(-) */
        for ( i = 0; i < pStruct->num_atoms; i ++ ) {
            iat = nCanon2AtnoRevrs[i];
            if ( pStruct->endpoint[i] ) {
                if ( 0 > (e=pVA[iat].nCMinusGroupEdge-1) || pBNS->edge[e].forbidden ||
                     0 <= FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e ) ) {
                    continue;
                }
                bFirst = ( (pVA[iat].cNumValenceElectrons == 5 && pc2i->nNumTgInChI == 1) ||
                           (pVA[iat].cNumValenceElectrons == 6 && pc2i->nNumTgInChI != 1)  );
                    /* many or no t-groups -> try O only first */
                    /* single t-group -> try only N first */
                if ( !(at_Mobile_H_Revrs && at_Mobile_H_Revrs[i].endpoint) ) {
                    /* missed tautomeric endpoint */
                    if ( bFirst && 
                         (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_MISSED_TAUT_1], e, INC_ADD_EDGE ))) {
                        goto exit_case_25;
                    }
                    if ( (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_MISSED_TAUT_ALL], e, INC_ADD_EDGE )) ) {
                        goto exit_case_25;
                    }
                }
                if ( bFirst && 
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_OTHER_TAUT_1], e, INC_ADD_EDGE ))) {
                    goto exit_case_25;
                }
                if ( (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_OTHER_TAUT_ALL], e, INC_ADD_EDGE )) ) {
                    goto exit_case_25;
                }
                if ( (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e, INC_ADD_EDGE )) ) {
                    goto exit_case_25;
                }
            } else
            if ( at2[iat].valence == 1 && at2[iat].charge == -1 &&
                 pVA[iat].cNumValenceElectrons == 6 &&
                 pVA[iN=at2[iat].neighbor[0]].cNumValenceElectrons == 5 && /* -O(-) */
                 !pStruct->endpoint[nAtno2CanonRevrs[iN]] &&
                 at2[iN].valence == 3 && at2[iN].chem_bonds_valence == 3 &&
                 !at2[iN].charge && !at2[iN].radical && 
                 0 <= (e=pVA[iN].nCPlusGroupEdge-1) && !pBNS->edge[e].forbidden &&
                 pBNS->edge[e].flow && /* NPlus edge */
                 0 <= (e1 = pVA[iat].nCMinusGroupEdge-1) && !pBNS->edge[e1].forbidden &&
                 pBNS->edge[e1].flow &&  /* OMinus edge */
                 0 > FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e ) &&
                 0 > FindInEdgeList( &ChangeableEdges[CHG_SET_AVOID], e1 )) {
                /* found >N-O(-) */
                int nNumO = 0, nNumOthers = 0;
                for ( k = 0; k < at2[iN].valence; k ++ ) {
                    neigh = at2[iN].neighbor[k];
                    if ( neigh == iat ) {
                        continue;
                    }
                    if ( pVA[neigh].cNumValenceElectrons == 6 &&
                         !pStruct->endpoint[neigh] &&
                         at2[neigh].valence == 1 && at2[neigh].num_H == 0 &&
                         at2[neigh].radical == 0 && at2[neigh].charge == -1 &&
                         at2[neigh].chem_bonds_valence == 1 ) {
                        nNumO ++;
                    } else
                    if ( at2[iN].bond_type[k] == BOND_TYPE_SINGLE &&
                         at2[neigh].valence > 1 &&
                         at2[neigh].valence < at2[neigh].chem_bonds_valence ) {
                        nNumOthers ++;
                    }
                }
                if ( nNumO != 1 && nNumOthers != 1 ) {
                    continue;
                }
                /* save charge edges: NPlus first, OMinus second */
                if ( (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NO_IN_NO2M2], e, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_NO_IN_NO2M2], e1, INC_ADD_EDGE ))   ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e, INC_ADD_EDGE )) ||
                     (ret = AddToEdgeList( &ChangeableEdges[CHG_SET_AVOID], e1, INC_ADD_EDGE ))) {
                    goto exit_case_25;
                }
            }
        }
        if ( !ChangeableEdges[CHG_SET_NO_IN_NO2M2].num_edges ||
             !ChangeableEdges[CHG_SET_OTHER_TAUT_ALL].num_edges ) {
            goto exit_case_25;
        }
        /* ------- finally, try to move charges from -NO2(2-) or to tautomeric endpoints ----*/
        for ( i = 0; i < ChangeableEdges[CHG_SET_NO_IN_NO2M2].num_edges; i += 2 ) {
            int nDeltaChargeExpected = 3; 
            /* change flow on O(-) to make it neutral; 3 new charges will be created:
               N(+), and two (-) on InChI endpoints
               alternatively, if we change flow on N to make N(+) then O(-) will
               be nutralized (-1 charge) and two (-) charges on taut. endpoints will be
               created (+2); the total change in this case would be (-1)+(+2) = +1
            */
            one_success = 0;
            delta = 1;
            pe  = pBNS->edge + ChangeableEdges[CHG_SET_NO_IN_NO2M2].pnEdges[i+1]; /* O(-) edge */
            pef = pBNS->edge + ChangeableEdges[CHG_SET_NO_IN_NO2M2].pnEdges[i]; /* >N- (+) edge */

            if ( !pe->flow )
                continue;
            pv1 = pBNS->vert + (v1 = pe->neighbor1);
            pv2 = pBNS->vert + (v2 = pe->neighbor12 ^ v1);

            pe->flow -= delta;
            pv1->st_edge.flow -= delta;
            pv2->st_edge.flow -= delta;
            pBNS->tot_st_flow -= 2*delta;

            for ( k = 0; !one_success && k <= CHG_LAST_SET; k ++ ) {
                if ( !ChangeableEdges[k].num_edges ) {
                    continue;
                }
                SetForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );
                RemoveForbiddenEdgeMask( pBNS, &ChangeableEdges[k], forbidden_edge_mask  );
                /* allow change of N(V) flower edge */
                pef->forbidden  &= forbidden_edge_mask_inv;
                
                ret = RunBnsTestOnce( pBNS, pBD, pVA, &vPathStart, &vPathEnd, &nPathLen,
                                      &nDeltaH, &nDeltaCharge, &nNumVisitedAtoms );

                if ( ret == 1 && ((vPathEnd == v1 && vPathStart == v2) ||
                                  (vPathEnd == v2 && vPathStart == v1)) &&
                                  nDeltaCharge == nDeltaChargeExpected ) {
                    /* Move (-) charge to =O and remove it an endpoint => nDeltaCharge == 0 */
                    ret = RunBnsRestoreOnce( pBNS, pBD, pVA, pTCGroups );
                    if ( ret > 0 ) {
                        nNumRunBNS ++;
                        one_success ++; /* 24 */
                    }
                }
                INCHI_HEAPCHK
            }
            cur_success += one_success;
            
            RemoveForbiddenEdgeMask( pBNS, &AllChargeEdges, forbidden_edge_mask );

            if ( !one_success ) {
                pe->flow += delta;
                pv1->st_edge.flow += delta;
                pv2->st_edge.flow += delta;
                pBNS->tot_st_flow += 2*delta;
            }
        }
exit_case_25:
        for ( i = 0; i < CHG_SET_NUM; i ++ ) {
            AllocEdgeList( &ChangeableEdges[i], EDGE_LIST_FREE );
        }

        CurrEdges.num_edges = 0; /* clear current edge list */
        if ( cur_success ) {
            tot_succes += cur_success;
            /* recalculate InChI from the structure */
            if ( 0 > (ret = MakeOneInChIOutOfStrFromINChI2( ip, sd, pBNS, pStruct, at, at2, at3, pVA, pTCGroups,
                                                            ppt_group_info, ppat_norm, ppat_prep ) ) ) {
                goto exit_function;
            }
            if ( (ret = FillOutExtraFixedHDataRestr( pStruct )) ) {
                goto exit_function;
            }
            if ( !pInChI[0]->nNum_H_fixed && !pStruct->pOneINChI[0]->nNum_H_fixed ) {
                goto exit_function;  /* no fixed-H found */
            }
            if ( (ret = FillOutCMP2FHINCHI( pStruct, at2, pVA, pInChI, pc2i )) ) {
                goto exit_function;
            }
            if ( !pc2i->bHasDifference ) {
                goto exit_function; /* nothing to do */
            }
        }
#undef CHG_SET_NN
#undef CHG_SET_MISSED_TAUT
#undef CHG_SET_OTHER_TAUT_O
#undef CHG_SET_OTHER_TAUT_N
#undef CHG_LAST_SET
#undef CHG_SET_AVOID
#undef CHG_SET_NUM
    }


exit_function:
    AllocEdgeList( &AllChargeEdges, EDGE_LIST_FREE );
    AllocEdgeList( &CurrEdges, EDGE_LIST_FREE );
    AllocEdgeList( &NFlowerEdges, EDGE_LIST_FREE );
    AllocEdgeList( &SFlowerEdges, EDGE_LIST_FREE );
    AllocEdgeList( &OtherNFlowerEdges, EDGE_LIST_FREE );
    AllocEdgeList( &FixedLargeRingStereoEdges, EDGE_LIST_FREE );
    AllocEdgeList( &AllBondEdges, EDGE_LIST_FREE );
    return ret < 0? ret : (pc2i->bHasDifference && tot_succes);
}
#endif
