/*
Copyright (c) 1993-2008, Cognitive Technologies
All rights reserved.

Разрешается повторное распространение и использование как в виде исходного кода,
так и в двоичной форме, с изменениями или без, при соблюдении следующих условий:

      * При повторном распространении исходного кода должны оставаться указанное
        выше уведомление об авторском праве, этот список условий и последующий
        отказ от гарантий.
      * При повторном распространении двоичного кода в документации и/или в
        других материалах, поставляемых при распространении, должны сохраняться
        указанная выше информация об авторском праве, этот список условий и
        последующий отказ от гарантий.
      * Ни название Cognitive Technologies, ни имена ее сотрудников не могут
        быть использованы в качестве средства поддержки и/или продвижения
        продуктов, основанных на этом ПО, без предварительного письменного
        разрешения.

ЭТА ПРОГРАММА ПРЕДОСТАВЛЕНА ВЛАДЕЛЬЦАМИ АВТОРСКИХ ПРАВ И/ИЛИ ДРУГИМИ ЛИЦАМИ "КАК
ОНА ЕСТЬ" БЕЗ КАКОГО-ЛИБО ВИДА ГАРАНТИЙ, ВЫРАЖЕННЫХ ЯВНО ИЛИ ПОДРАЗУМЕВАЕМЫХ,
ВКЛЮЧАЯ ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ, НО НЕ
ОГРАНИЧИВАЯСЬ ИМИ. НИ ВЛАДЕЛЕЦ АВТОРСКИХ ПРАВ И НИ ОДНО ДРУГОЕ ЛИЦО, КОТОРОЕ
МОЖЕТ ИЗМЕНЯТЬ И/ИЛИ ПОВТОРНО РАСПРОСТРАНЯТЬ ПРОГРАММУ, НИ В КОЕМ СЛУЧАЕ НЕ
НЕСЁТ ОТВЕТСТВЕННОСТИ, ВКЛЮЧАЯ ЛЮБЫЕ ОБЩИЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ ИЛИ
ПОСЛЕДОВАВШИЕ УБЫТКИ, СВЯЗАННЫЕ С ИСПОЛЬЗОВАНИЕМ ИЛИ ПОНЕСЕННЫЕ ВСЛЕДСТВИЕ
НЕВОЗМОЖНОСТИ ИСПОЛЬЗОВАНИЯ ПРОГРАММЫ (ВКЛЮЧАЯ ПОТЕРИ ДАННЫХ, ИЛИ ДАННЫЕ,
СТАВШИЕ НЕГОДНЫМИ, ИЛИ УБЫТКИ И/ИЛИ ПОТЕРИ ДОХОДОВ, ПОНЕСЕННЫЕ ИЗ-ЗА ДЕЙСТВИЙ
ТРЕТЬИХ ЛИЦ И/ИЛИ ОТКАЗА ПРОГРАММЫ РАБОТАТЬ СОВМЕСТНО С ДРУГИМИ ПРОГРАММАМИ,
НО НЕ ОГРАНИЧИВАЯСЬ ЭТИМИ СЛУЧАЯМИ), НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ДАЖЕ ЕСЛИ ТАКОЙ
ВЛАДЕЛЕЦ ИЛИ ДРУГОЕ ЛИЦО БЫЛИ ИЗВЕЩЕНЫ О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ И ПОТЕРЬ.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
      this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
    * Neither the name of the Cognitive Technologies nor the names of its
      contributors may be used to endorse or promote products derived from this
      software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/


/*********************************************************************/
/*                                                                   */
/*		Punctuation signs recognition                        */
/*                                                                   */
/*********************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "nt_types.h"
#include "struct.h"
#include "func.h"
#define PUNCT_CORRECTION0 //Loginov
//#define SAVE_FEAT //Loginov
#include "ligas.h"
#include "lang.h"
#include "tuner.h"
#include "status.h"
#include "linutil.h"	// 31.05.2002 E.P.

#include"compat_defs.h"

extern BYTE fax1x2;
extern INT pitchsize;
extern BYTE db_status;
extern INT line_number;
extern cell *accadr1;
extern cell *accadr2;
extern BYTE line_tabcell;

#define HPERMIN 4
#define KEGM    14
#define FEAT_SIZE 40

static PBYTE rstr;
static INT italic;
static B_LINES bl;
static cell *clist[4];
PBYTE sv_fantom=NULL;

static void order();
static void bad_to_dust();
static void glue_dust();
static INT exclam (cell *,cell *,B_LINES *);
static cell *let_gl(cell *,cell *,cell *,cell *,B_LINES *);
static void dots();
static void quockets();
static void dust_to_bad(cell *);
static void punctsign(cell **,cell **);
static void intval (cell *,cell *);
static void no_cut(cell *);
static INT dustpos(INT,cell *);
#ifdef PUNCT_CORRECTION
 //static INT exist_prev_next(cell *c,INT *dif1,INT *dif2);
//static INT get_dust_status(cell *c,BYTE *dust_st);
//static INT dust_pos_new(cell *);
INT is_dash(cell *c);
INT is_dust_2(cell *c);
INT is_dust(cell *);
INT is_point_stop(cell *c);
#endif
static INT chkquot(INT,INT,cell *);
static INT chkstar(INT,INT,cell *);
static INT chkdotcom(INT,INT,cell *);
static INT chkdash(INT,INT,cell *);
static INT chkplus(INT,INT,cell *);
static INT chkslash(INT,INT,cell *);
static INT chkcircle(INT,INT,cell *);
static INT chkquock(INT,INT,cell *);
static INT chkquocks(INT,INT,cell *);
static INT contain(cell *new, cell *old);
cell *hide(cell *C);

static void czech_dt_glue_apostroph(); // 07.09.2000 E.P.


INT check_shevron(cell *c,INT flag_qual); //Alik

//
// kill temporary twin flags BAD+DUST for pass4
//
void clear_punct_twin_flags(void)
{
cell *c,*e;
for(c=cell_f()->next, e=cell_l(); c!=e; c=c->next )
    {
    if( c->flg==(c_f_bad|c_f_dust) )
        dust_to_bad(c);
    if( c->nvers && (c->flg&c_f_bad) )
        c->flg = c_f_let;
    }
return;
}

void punct()
 {
 cell *c1,*c2,*c;
 BYTE l;
 INT x,d;

 if (language == LANG_RUSSIAN)  sv_fantom=NULL;
 snap_newpass('e');
 quockets();

 // ACC_ROOF_INF над d,t в Чешском похож на апостроф. 07.09.2000 E.P.
 if (language==LANG_CZECH)
	czech_dt_glue_apostroph();

 bad_to_dust();
 glue_dust();
 dots();
 order();

 italic=0;
 c1=cell_f();
 while ((c2=c1->next)!=NULL)
  {
       if ((c1->font|c1->font_new)&c_fp_it)
        italic=1;
       if ((c1->font|c1->font_new)&c_fp_str)
        italic=0;
       if( (c1->pos_inc&erect_rot) && c1->stick_inc>256 )  // OLEG
        italic=1;
       if (c1->nextl->prev==c1 ||
                //     (c2->flg & (c_f_space|c_f_punct)) ||
          (c1->flg & (c_f_solid|c_f_confirmed)) // Vald
          )
         {c1=c1->nextl; continue;}
       x=c1->col+c1->w;
       if (!italic && c1->nextl->col<x ||
           c1->nextl->col-x<=1 &&
           c1->cg_flag&c_cg_cutr &&
           c1->nextl->cg_flag&c_cg_cutl &&
           c1->next->cg_flag&c_cg_cutl &&
           c1->nextl->prev->cg_flag&c_cg_cutr)
        {
            if (db_status)
              snap_newcell(c1->next);
            if (snap_activity('e'))
            {
               snap_show_text("delete cutted dust");
               snap_monitor();
            }
             /*
             c1->next=c1->nextl;
             c1->nextl->prev=c1;
             */
             hide(c2);
             c1=c1->nextl;
             continue;
        }
        if(language != LANG_RUSSIAN )
        {
            if (memchr("fFrTP",(l=c1->vers[0].let),5))
              x-=(c1->w)/2;
            if (memchr("vVwWyY7",l,7))
              x-=(c1->w)/4;
            if (((c1->font|c1->font_new)&c_fp_it || italic) && memchr("dlEHIJMNSUZ1t6",l,14))
              x-=(c1->w)/4;
              // Interference i_left_accent ~ м
            if (
				// Конфликтный код 07.09.2000 E.P.
			    !is_baltic_language(language) && 	// 17.07.2001 E.P.
			    !is_turkish_language(language) && (	// 30.05.2002 E.P.
				!is_cen_language(language) && l==i_left_accent ||
				l==i_right_accent ) ||

				// Балтийские палки. 10.07.2001 E.P.
				is_baltic_language(language) &&
					(
					l==II_bottom_accent || l==i_bottom_accent ||
					l==l_bottom_accent
					) ||
				// Турецкие палки. 30.05.2002 E.P.
				is_turkish_palka(l)
				)
              x-=(c1->w)/4;
        }
        else
        {
            //    if (memchr("Ј’ђ",(l=c1->vers[0].let),5))  Paul  10-14-96
            if (memchr("ѓЈ’ђ",(l=c1->vers[0].let),4))
              x-=(c1->w)/2;
            if (memchr("г“7",l,7))
              x-=(c1->w)/4;
            //    if ((c1->font&c_fp_it || italic) && memchr("€ЌЏ16Ў",l,14))Paul  10-14-96
            if (((c1->font|c1->font_new)&c_fp_it || italic) &&
				!(memchr("Ђ„†Љ•–™љ›њ",l,10) &&
					!is_russian_turkish_conflict(l) // 21.05.2002 E.P.
				 )
				)
              x-=(c1->w)/4;
              // Interference i_left_accent ~ м
            if (
				// Конфликтный код 07.09.2000 E.P.
				!is_baltic_language(language) && 	// 17.07.2001 E.P.
				!is_turkish_language(language) && (	// 30.05.2002 E.P.
				!is_cen_language(language) && l==i_left_accent
				|| l==i_right_accent
				) ||

				// Балтийские палки. 10.07.2001 E.P.
				is_baltic_language(language) &&
					(
					l==II_bottom_accent || l==i_bottom_accent ||
					l==l_bottom_accent
					) ||
				// Турецкие палки. 30.05.2002 E.P.
				is_turkish_palka(l)
			   )
              x-=(c1->w)/4;
        }
        c1=c1->nextl;

		//AK add crashguard
		if ( (!AKCellInChain(c2) || !AKCellInChain(c1)) )
			break;

        while (c2!=c1)
        {
              if (c2->flg & c_f_punct)  { c2=c2->next;  continue; }
              get_b_lines(c2,&bl);
              c=c1->prevl;
              d=0;
              if (memchr("AL",l,2) && !((c->font|c->font_new)&c_fp_it) && c2->row+c2->h<c->row+c->h/2)
                  d=(c->w)/2;
              if (!(c2->flg&c_f_bad) &&
                 (x-d>c2->col+(c2->w)/2 ||
                 /*      accent_tab[l] && c->col+c->w>c2->col && c2->row<bl.bm ||*/
                  !((c->font|c->font_new)&c_fp_it) && c2->row+c2->h>=bl.b3-3 && c2->w<=4 &&
                  c->col+c->w>c2->col && strchr("adhijlmnquzAIHKLMNRZ12",l)!=NULL))
              {
              /*
              if( c2->main_acc )
                { // OLEG : save accent for pass2
                cell    *cc=c2->main_acc, *cn=cc->next;
                clist[0]=cc;
                clist[1]=c2;
                compose_cell(2,clist,cc);
                if( cc->accent_leader )
                    cc->accent_leader=0;
                c2=cn;
                }
              else
              */
                {
                no_cut(c2);
                c2=hide(c2);
                c2=c2->next;
                }
              }
              else
              {
                   if (db_status)
                    snap_newcell(c2);
                   if (snap_activity('e'))
                   {
                      snap_show_text("interval begin");
                      snap_monitor();
                   }
                   punctsign(&c1,&c2);  // AL 940319
                   intval(c1,c2);
                   if (db_status)
                      snap_newcell(c1->prev);
                   if (snap_activity('e'))
                   {
                      snap_show_text("interval end");
                      snap_monitor();
                   }
                   break;
              }
        }//end of while (c2!=c1)
  }//end of while ((c2=c1->next)!=NULL)
 for (c1=cell_f(),c2=c1->nextl,c=c1->next; c->next; c=c->next)
  if (c->flg&(c_f_let|c_f_bad) && !(c->flg&(c_f_dust|c_f_punct)))
   {c1=c; c2=c->nextl;}
  else
   if (
        (!(c1->flg&c_f_fict) &&
        (c1->flg&c_f_bad || c1->vers[0].let=='i' && c1->vers[0].prob==128) &&
        c->col+c->w/2<c1->col+c1->w ||
        !(c2->flg&c_f_fict) &&
        (c2->flg&c_f_bad || c2->vers[0].let=='i' && c2->vers[0].prob==128) &&
        c->col+c->w/2>c2->col)
#ifdef PUNCT_CORRECTION
        ||  ( language==LANG_RUSSIAN && is_dust_2(c) )
#endif
      )
    {
       if (db_status)
        snap_newcell(c);
       if (snap_activity('e'))
        {
        snap_show_text("delete dust");
        snap_monitor();
        }
       c=hide(c);
    }

 if (snap_activity('e'))
  {
  snap_show_text("punctuation end");
  snap_monitor();
  }

 }

 static void order()
 {
	cell *c1,*c2,c;
	//AK add c/g (case of c1 = cell_l()
	if ( cell_f()->next != cell_l() )
	{
	for (c1=(cell_f())->next; (c2=c1->next)->next!=NULL; c1=c2)
	if (c1->col==c2->col && c1->w>c2->w)
	{
   memcpy(&c,c1,sizeof(cell));
   memcpy(c1,c2,sizeof(cell));
   c1->next=c.next; c1->prev=c.prev;
   c.next=c2->next; c.prev=c2->prev;
   if (c1->flg&(c_f_dust|c_f_punct))
    {
    if (!(c.flg&(c_f_dust|c_f_punct)))
     (c.prevl)->nextl=(c.nextl)->prevl=c2;
    }
   else
    {
    if (c.flg&(c_f_dust|c_f_punct))
     (c1->prevl)->nextl=(c1->nextl)->prevl=c1;
    else
     {
     c1->nextl=c.nextl; c1->prevl=c.prevl;
     c.nextl=c2->nextl; c.prevl=c2->prevl;
     }
    }
   memcpy(c2,&c,sizeof(cell));
   c2=c2->prev;
   if (!(c2->prev->flg&c_f_fict))
    c2=c2->prev;
   } //for if
  } //if
 }

#define PROBMIN    40
#define PROBOK     120
#define PROBOK_ceo 190

static void bad_to_dust()
 {
 cell *c, *cc;
 INT r;

 for (c=cell_f()->nextl; c->next!=NULL; c=c->nextl)
  {
  //  Oleg
  //if (!tsimple(c))
  //  continue;
  get_b_lines(c,&bl);
  rstr=NULL;
  if(
      (c->flg&c_f_bad ||
       c->vers[0].prob<PROBOK ||                // Oleg
       memchr("ceo<>",c->vers[0].let,4) && c->vers[0].prob<PROBOK_ceo ||
       language==LANG_RUSSIAN && memchr("Єўбэкн",c->vers[0].let,6) &&
                                 c->vers[0].prob<PROBOK_ceo ||
       language==LANG_RUSSIAN && memchr("ўн",c->vers[0].let,2) &&
       c->stick_inc>300 && c->vers[0].prob<PROBOK_ceo+10     ||
       language==LANG_RUSSIAN && memchr("ЁҐ®",c->vers[0].let,3) &&
       c->vers[0].prob<PROBOK_ceo-20
     ) && c->h<=bl.ps && c->row+2>=bl.b2 && c->row+c->h-2<=bl.b3 &&
          (r=chkquocks(bl.ps,2,c))!=0 && check_shevron(c,1)>=3)
   {
   c->vers[0].let=(r<0)?left_quocket:right_quocket;
   c->vers[0].prob=254;
   c->vers[1].let=0;
   c->nvers=1;
   c->flg=c_f_let;
   }
  if ((c->flg&c_f_bad || c->vers[0].prob<PROBMIN) &&
      c->h<=bl.ps &&
      (c->row+((fax1x2)?2:0)+1>=bl.bm ||
       c->row+c->h-1-((fax1x2)?2:0)<=bl.bm ||
       c->row+1>=bl.b2 && c->row+c->h-1<=bl.b3 && c->h<bl.ps ||
       c->cpos==ce_p_ex && (c->h>c->w || c->h<=2*bl.ps/3)))
   {
   if (db_status)
    snap_newcell(c);
   if (snap_activity('e'))
    {
    snap_show_text("bad to dust");
    snap_monitor();
    }
   c->flg=(c_f_dust|c_f_bad);
   (cc = c->prevl)->nextl=c->nextl;
   c->nextl->prevl=c->prevl;
   err_pnlet(c);  // ?? AL 940319
   c = cc;
   }
  }
 }

#define DCDUST  2

static void glue_dust()
 {
 cell *c1,*c2,*c3,*c4;cell *cc1;
 INT h,s,m1,m2,m3,m4;

 for (c1=(cell_f())->next; c1 && (c2=c1->next)!=NULL; c1=c1->next)
  if (c1->flg&c2->flg&c_f_dust)
   {
   get_b_lines(c1,&bl);
   h=bl.ps;
   if (c1->w>h/2 || c2->w>h/2)
    continue;
   m1=c1->col+(c1->w)/2;
   m2=c2->col+(c2->w)/2;
   if (c1->row>=bl.b1-2 && c1->row+c1->h<=bl.b3+2 &&
       c2->row>=bl.b1-2 && c2->row+c2->h<=bl.b3+2 &&
       abs(m1-m2)<=DCDUST)
    {
    s=c1->h+c2->h;
    if ((c3=c2->next)!=NULL && c3->flg&c_f_dust && c3->w<=h/2)
     {
     m3=c3->col+(c3->w)/2;
     if (c3->row>=bl.b1-2 && c3->row+c3->h<=bl.b3+2 &&
	 abs(m1-m3)<=DCDUST && abs(m2-m3)<=DCDUST)
      {
      s+=c3->h;
      if ((c4=c3->next)!=NULL && c4->flg&c_f_dust && c4->w<=h/2)
       {
       m4=c4->col+(c4->w)/2;
       if (c4->row>=bl.b1-2 && c4->row+c4->h<=bl.b3+2 &&
	   abs(m1-m4)<=DCDUST && abs(m2-m4)<=DCDUST && abs(m3-m4)<=DCDUST)
	s+=c4->h;
       else
	c4=NULL;
       }
      else
       c4=NULL;
      }
     else
      c3=c4=NULL;
     }
    else
     c3=c4=NULL;
    if (c3==NULL &&
	(c1->h<=4*c1->w/3 && c2->h<=4*c2->w/3 || exclam(c1,c2,&bl)))
     continue;
    if ((s>h || (c3!=NULL || fax1x2) && s>=h-1) &&
	(c1->row<bl.b2 || c2->row<bl.b2 || c3!=NULL &&
		 (c3->row<bl.b2 || c4!=NULL && c4->row<bl.b2)) &&
	(c1->row+c1->h>bl.bm || c2->row+c2->h>bl.bm || c3!=NULL &&
		 (c3->row+c3->h>bl.bm || c4!=NULL && c4->row+c4->h>bl.bm)))
     {
     if (db_status)
      snap_newcell(c1);
     if (snap_activity('e'))
      {
      snap_show_text("glue of dusts: before");
      snap_monitor();
      }
     cc1=let_gl(c1,c2,c3,c4,&bl);
     if( cc1 )
         {
         c1=cc1;
         if (db_status) snap_newcell(c1);
         if (snap_activity('e'))
          {
          snap_show_text("glue of dusts: after");
          snap_monitor();
          }
         }
    else
        {
        return ; // OLEG : restruct line
        }
     }
    }
   }
 }

static INT exclam(cell *c1,cell *c2,B_LINES *bl)
 {
 cell *c,*cc;

 c=(c1->row<c2->row)?c1:c2;
 if (c->row+c->h<=bl->bm && 5*c->h>3*bl->ps && 2*c->w<=c->h &&
     dustpos(bl->ps,c)<=3)
  {
  for (cc=c; cc->flg&c_f_dust || !(cc->flg&(c_f_let|c_f_bad|c_f_fict));
							      cc=cc->prev) ;
  c->flg=c_f_let;
  c->nvers=1;
  c->vers[0].let='!'; c->vers[0].prob=254;
  c->vers[1].let=0;
  c->prevl=cc;
  c->nextl=cc->nextl;
  cc->nextl=cc->nextl->prevl=c;
  if (dot_excl(c)!=NULL)
   {
   if (db_status)
    snap_newcell(c1);
   if (snap_activity('e'))
    {
    snap_show_text("dust to exclam");
    snap_monitor();
    }
   return 1;
   }
  c->flg=c_f_dust;
  cc->nextl=c->nextl;
  cc->nextl->prevl=cc;
  err_pnlet(c);  // AL 940319
  }
 return 0;
 }

static cell *let_gl(cell *c1,cell *c2,cell *c3,cell *c4,B_LINES *bl)
 {
 cell *c, *cp;
 extern INT nIncline;
 INT r,n;
#define MBI 1
#define MBE 2

 cp = c1->prev;
 c=new_cell();
 c->flg=c_f_let;
 clist[0]=c1;
 clist[1]=c2;
 if (c3!=NULL)
  {
  clist[2]=c3;
  if (c4!=NULL)
   {
   clist[3]=c4;
   n=4;
   }
  else
   n=3;
  }
 else
  n=2;
 // AL make all decidions BEFORE deletion of cells
 r=0;
 if (c1->row+c1->h-1<=bl->b2 && abs(c1->h-c1->w)<=MAX(1,bl->ps/8) ||
     c2->row+c2->h-1<=bl->b2 && abs(c2->h-c2->w)<=MAX(1,bl->ps/8) ||
     c3!=NULL &&
     (c3->row+c3->h-1<=bl->b2 && abs(c3->h-c3->w)<=MAX(1,bl->ps/8) ||
      c4!=NULL &&
      c4->row+c4->h-1<=bl->b2 && abs(c4->h-c4->w)<=MAX(1,bl->ps/8)))
  r|=MBI;
 if (c1->row>=bl->bm && abs(c1->h-c1->w)<=MAX(1,bl->ps/8) ||
     c2->row>=bl->bm && abs(c2->h-c2->w)<=MAX(1,bl->ps/8) ||
     c3!=NULL &&
     (c3->row>=bl->bm && abs(c3->h-c3->w)<=MAX(1,bl->ps/8) ||
      c4!=NULL && c4->row>=bl->bm && abs(c4->h-c4->w)<=MAX(1,bl->ps/8)))
  r|=MBE;
 // AL
 // AL OK (returns new "c1")
if( !compose_cell(n,clist,c) )
    {
    free_cell(c);
    return NULL;
    }
 c->reasno=0;
 c->cpos=0;
 c->font=0;
 c->bdiff=0;
 c->difflg=0;
 c->cg_flag=0;
 c->dens=255;
 c->keg=(BYTE)bl->ps;
 c->nvers=0;
 // AL-JOE decicion-making was here; all c1-c4 were deleted
 if( (r&MBI) && !(language==LANG_RUSSIAN&&!langUkr&&!langSer))
  {
  c->vers[c->nvers].let='i';
  c->vers[c->nvers].prob=128;
  (c->nvers)++;
  }
 if (r&MBE)
  {
  c->vers[c->nvers].let='!';
  c->vers[c->nvers].prob=128;
  (c->nvers)++;
  }
 if( language!=LANG_RUSSIAN )
     {
     c->vers[c->nvers].let='l';
     c->vers[c->nvers].prob=(c->nvers)?100:128;
     (c->nvers)++;
     }
 c->vers[c->nvers].let=0;
 if( language==LANG_RUSSIAN && c->nvers==0 )
    {
    c->vers[0].let=bad_char;
    }

 insert_cell(c,cp);
 return c;
 }

static void dots()
 {
 cell *c,*cc,csv;
 BYTE let;
 INT i,nv;
 version vers[VERS_IN_CELL];

 for (c=(cell_f())->next; c->next!=NULL; c=c->next)
  {
  c->left=c->col;
  c->right=c->col+c->w;
  if (c->flg&(c_f_dust|c_f_punct))
   continue;
  get_b_lines(c,&bl);
  if ((let=c->vers[0].let)==liga_ri && (cc=dot_ri(c))!=NULL ||
      (let=='i' || let=='j') && (cc=dot_ij(c))!=NULL ||
      (
	    ( language == LANG_POLISH &&
            ( let == ZZ_dot_accent || let == z_dot_accent ) ||
		  // 16.07.2001 E.P.
		  language == LANG_LITHUANIAN &&
            ( let == EE_dot_accent || let == e_dot_accent ) ||
		  // 30.05.2002 E.P.
		  language == LANG_TURKISH &&
            let == II_dot_accent
		) &&
            (cc=dot_ij(c))!=NULL ) ||
      (let==invers_exm || let==invers_qm) && (cc=dot_inv(c))!=NULL ||
      (let=='!' || let=='?') && (cc=dot_excl(c))!=NULL)
   {
   if (db_status)
    snap_newcell(cc);
   if (snap_activity('e'))
    {
    snap_show_text("delete dot");
    snap_monitor();
    }
   clist[0]=c;
   clist[1]=cc;
   // AL OK
   compose_cell(2,clist,c);
   if (let=='!' || let=='?')
    {c->left=c->col; c->right=c->col+c->w;}
   }

  for(i=0;i<c->nvers;i++)
    {
    vers[i]=c->vers[i];
    c->vers[i].let = let_sans_acc[c->vers[i].let];
    }
  if ((accent_tab[let] && accent_tab[let]!=ACC_DOT && type_acc(c,FALSE) ||
            c->bottom_accent && find_bottom_accent(c))   // 17.10.97 E.P.
      && accadr1!=NULL )
   {
   cc=accadr1;
   if (db_status)
    snap_newcell(cc);
   if (snap_activity('e'))
    {
    snap_show_text("delete accent");
    snap_monitor();
    }
   clist[0]=c;
   clist[1]=cc;
   // AL OK
   compose_cell(2,clist,c);
   if( c->accent_leader )
    c->accent_leader=0;
   }
   /*
  else if( accent_tab[let] && accent_tab[let]!=ACC_DOT &&
            (c->next->flg&(c_f_dust|c_f_punct)) &&
            (c->next->flg_new&c_fn_acccap) )
    { // OLEG : forming accent with cap for pass2
    cc=c->next;
    if (db_status)
        snap_newcell(cc);
    if (snap_activity('e'))
        {
        snap_show_text("delete accent satellit");
        snap_monitor();
        }
    clist[0]=c;
    clist[1]=cc;
    compose_cell(2,clist,c);
    if( c->accent_leader )
        c->accent_leader=0;
    }
    */
  for(i=0;i<c->nvers;i++)
    {
    c->vers[i]=vers[i];
    }
  if (accent_tab[let]& (ACC_2DOT
		|ACC_DOUBLE_RIGHT	// 31.08.2000 E.P.
		) && accadr2!=NULL) // ACC_2DOT 30.08.2000 E.P.
   {
   cc=accadr2;
   if (db_status)
    snap_newcell(cc);
   if (snap_activity('e'))
    {
    snap_show_text("delete second dot or double right accent");
    snap_monitor();
    }
   clist[0]=c;
   clist[1]=cc;
   // AL OK
   compose_cell(2,clist,c);
   if( c->accent_leader )
    c->accent_leader=0;
   }
  if ((let==bad_char || c->vers[0].prob<PROBMIN) && !(c->flg&c_f_dust))
   {
   if (c->cpos==ce_p_ex && c->h>c->w)
    {
    if (db_status)
     snap_newcell(c);
    if (snap_activity('e'))
     {
     snap_show_text("bad to dust");
     snap_monitor();
     }
    (c->prevl)->nextl=c->nextl;
    (c->nextl)->prevl=c->prevl;
    c->flg=c_f_dust|c_f_bad;
    err_pnlet(c);  // ALIF 940328
    }
   else
    {
    memcpy(&csv,c,sizeof(cell));
    short_recog_cell(c);
    levcut(c,1);
    for (nv=c->nvers,i=0; i<nv; i++)
     if (c->vers[i].let=='i') break;
    if (i<nv)
     {
     c->nvers=1;
     c->vers[0].let='i'; c->vers[0].prob=128;
     c->vers[1].let=0;
     if (db_status)
      snap_newcell(c);
     if (snap_activity('e'))
      {
      snap_show_text("bad to i");
      snap_monitor();
      }
     }
    else memcpy(c,&csv,sizeof(cell));
    }
   }
  if ((c->flg==c_f_bad || c->vers[0].prob<=PROBMIN) && !(c->flg&c_f_dust) &&
      c->cpos==ce_p_ex && c->h<=2*bl.ps/3)
   {
   if (db_status)
    snap_newcell(c);
   if (snap_activity('e'))
    {
    snap_show_text("bad to dust");
    snap_monitor();
    }
   (c->prevl)->nextl=c->nextl;
   (c->nextl)->prevl=c->prevl;
   c->flg=c_f_dust;
   err_pnlet(c);  // AL 940320
   }
  }
 }

static void quockets()
 {
 cell *c;
 BYTE let;
 INT h;

 for (c=(cell_f())->nextl; c->next!=NULL; c=c->nextl)
  {
  get_b_lines(c,&bl);
  h=bl.ps;
  if (((let=c->vers[0].let)=='<' || let=='>') &&
      c->next->flg&(c_f_let|c_f_bad) && c->next->vers[0].let==let &&
       abs(c->h-c->next->h)<=(c->h+c->next->h)/4 &&
       MIN(c->h,c->next->h)<=h &&
       c->col+c->w-c->next->col<=(c->w+c->next->w)/3 &&
      abs(c->row+c->h/2-(c->next->row+c->next->h/2))<=(c->h+c->next->h)/6)
   {
   if (db_status)
    snap_newcell(c);
   if (snap_activity('e'))
    {
    snap_show_text("quocket: before");
    snap_monitor();
    }
   c->nvers=1;
   c->vers[0].let=(let=='<')?left_quocket:right_quocket;
   c->vers[0].prob=254;
   c->vers[1].let=0;
   clist[0]=c;
   clist[1]=c->next;
   // AL OK
   compose_cell(2,clist,c);
   c->flg=c_f_let;
   c->left=c->col;
   c->right=c->col+c->w;
   if (snap_activity('e'))
    {
    snap_show_text("quocket: after");
    snap_monitor();
    }
   }
  }
 }

static void punctsign(cell **ac1,cell **ac2)
 {
 INT h,d,dd,dp,fl,dc,p,lr,a;
 BYTE let,str[80];
 cell *c;
 cell *c1;
 cell *c2;
 c1 = *ac1;
 c2 = *ac2;


 get_b_lines(c1,&bl);
 h=bl.ps;
 d=0;
 if (((let=c1->vers[0].let)=='!' || let=='?') && (c1->font|c1->font_new)&c_fp_it)
  d=-(h/10+2);
 if ((let=='J'|| let=='f') && c1->cpos&ce_p_Ql || let=='j')
  d=h/10+2;
 while (c2!=c1)
  {
  if( c2->flg==c_f_punct )
      {
      if (snap_activity('e'))
        {
        snap_show_text("skip old punct cell");
        snap_monitor();
        }
      c2 = c2->next;
      continue;
      }
  get_b_lines(c2,&bl);
  h=bl.ps;
  fl=0;
  dd=0;
  if (((c1->font|c1->font_new)&c_fp_it || c1->vers[0].let=='A') &&
      c2->row+c2->h<c1->row+c1->h/2)
   dd=h/10+1;
  if (c2->col+(c2->w)/2<=c1->col+1+d+dd &&
      c1->col-c2->col+(c1->w-c2->w)/2+dd>=h/6)
   {
   dp=dustpos(h,c2);

   if (db_status)
    snap_newcell(c2);
   if (snap_activity('e'))
    {
    sprintf(str,"punct recog, dustpos=%u",dp);
    snap_show_text(str);
    snap_monitor();
    }
   if (dp==5 && c2->row>bl.b3 && c2->row-bl.b3<=2 ||
      (5*c2->w>=c2->h || c2->w<=2 && !(c1->font&c_fp_ser)) &&
      ((p=c2->h+c2->w)>=HPERMIN && 5*p>=h-1 || h<=KEGM) &&
      (!dp || dp<5 && c2->col+(c2->w)/2<c1->col+d))
    {
    fl=1; dc=0; rstr=NULL;
    if (chkstar(h,dp,c2))
     c2->vers[0].let='*';
    else
     {
     if (chkquot(h,dp,c2))
      c2->vers[0].let=(dp<=1)?'"':
			low_quotes;	// Макрос 31.05.2001 E.P.
     else
      {
      if ((lr=chkquock(h,dp,c2))!=0)
       c2->vers[0].let=(lr<0)?'<':'>';
      else
       {
       if ((lr=chkquocks(h,dp,c2))!=0 && check_shevron(c2,1)>=3 )
	c2->vers[0].let=(lr<0)?left_quocket:right_quocket;
       else
	{
	if ((dc=chkdotcom(h,dp,c2))>0)
        {
           c2->vers[0].let=(dc&1)?((dp>2)?'.':':'):((dp>2)?',':0x27);
           if( line_tabcell && c2->vers[0].let==',' && 4*c2->h<=5*c2->w )
                c2->vers[0].let='.' ;
        }
	else
	 {
	 if (chkdash(h,dp,c2))
         {
             if (dp==1 || dp==2)
             {
                 if (5*c2->w<4*h || 3*c2->h>c2->w ||
                     15*c2->h>4*c2->w && !pitchsize)
                 {

                       c2->vers[0].let='-';

                 }
                 else
                  {
                     if ((3*c2->w>4*h || !pitchsize && 12*c2->w>11*h) &&
                         5*c2->h<c2->w || 9*c2->h<c2->w || 7*c2->w>12*h)
                      c2->vers[0].let='_';
                     else
                     {
                         if (
                               (
                                  (c=c2->prev)->prev==NULL ||
                                  (a=c2->col-c->col-c->w)>=5*h/8 ||
                                  !pitchsize && a>=h/2
                               ) &&
                               (
                                  (c=c2->next)->next==NULL ||
                                  (a=c->col-c2->col-c2->w)>=5*h/8 ||
                                  !pitchsize && a>=h/2 ||
                                  a<0 &&
                                  c2->col+c2->w>c->col+c->w &&
                                  (c=c->next)->next==NULL ||
                                  (a=c->col-c2->col-c2->w)>=5*h/8 ||
                                  !pitchsize && a>=h/2
                               )
                            )
                            c2->vers[0].let='_';
                         else
                            c2->vers[0].let='-';
                     }
                  }
             }
             else
                c2->vers[0].let='=';
         }
	 else
	  {
	  if (chkplus(h,dp,c2))
	   c2->vers[0].let='+';
	  else
	   {
	   if (chkslash(h,dp,c2))
	    c2->vers[0].let='/';
	   else
	    {
	    if (chkcircle(h,dp,c2))
	     c2->vers[0].let=(dp<=1)?'O':'o';
	    else
	     fl=0;
	    }
	   }
	  }
	 }
	}
       }
      }
     }
    }
   }
  if (fl && c2->prev->flg==c_f_let &&
      ( (let=c2->prev->vers[0].let)=='g' ||
	  	let=='r' ||
		language==LANG_TURKISH && let==g_semicircle // 27.06.2002 E.P.
	  ) &&
      c2->prev->cg_flag&c_cg_cutr && c2->cg_flag&c_cg_cutl &&
      abs(c2->row-c2->prev->row)<=2)
   fl=0;
  if (fl)
   {
   c2->flg^=(c_f_punct|c_f_dust);
   c2->vers[0].prob=254;
   if(0)
   if( c2->flg & (c_f_bad|c_f_let) )
        {
        cell *t,*n;
        if( c2->nextl==(cell *)0xffff0000 ||
            c2->prevl==(cell *)0xffff0000 )
            {
            for(t=c2->prev;t;t=t->prev)
                {
                if( t->flg&(c_f_let|c_f_bad|c_f_fict) )
                    break;
                }
            n=t->nextl;
            t->nextl=c2;
            c2->prevl=t;
            n->prevl=c2;
            c2->nextl=n;
            }
        }
   if (dc<3 && (!dc || dp<=2 || (c=c2->prev)->flg==c_f_fict ||
						   !(c->font&c_fp_undrln)))
    {
    c2->vers[1].let=0;
    c2->nvers=1;
    }
   else
    {
    if (dp && dp!=4)
     c2->vers[1].let=',';
    else
     {c2->vers[0].let=','; c2->vers[1].let='.';}
    c2->vers[1].prob=254;
    c2->vers[2].let=0;
    c2->nvers=2;
    }
   if (db_status) snap_newcell(c2);
   if (snap_activity('e'))
    {
    snap_show_text("punct recog OK");
    snap_monitor();
    }
   }
  else
   {
   if (c2->flg&c_f_bad)
   {
    dust_to_bad(c2);
        if (snap_activity('e'))
         {
             sprintf(str,"dust to bad");
             snap_show_text(str);
             snap_monitor();
         }
   }
   else
    {
    if( multy_language && c2->w>SMALL_SIZE &&
        c2->row>bl.b1 && c2->row+c2->h<bl.b4 )
        {
        dust_to_bad(c2);

				// Nick 1.06.2001
		if( c2->nvers <= 0 )
		  c2->flg = c_f_bad;

        c2->flg_new |= c_fn_temp;


        if (snap_activity('e'))
         {
             sprintf(str,"dust to bad");
             snap_show_text(str);
             snap_monitor();
         }
        }
    else
        {
        cell *cc2;
        cc2 = c2;

        no_cut(c2);
        c2=hide(c2);
            if (snap_activity('e'))
             {
                 sprintf(str,"kill cell");
                 snap_show_text(str);
                 snap_monitor();
             }
        if (*ac1==cc2)
          *ac1=c2->next;
        if (*ac2==cc2)
          *ac2=c2->next;
        }
    }
   }
  c2=c2->next;
  }
 }

#define BASEOK 15
/////////////////
/////////////////
static INT dustpos(INT h,cell *c)

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

	Counting the dust position in the string for cell
	Returns:
	0 - in the upper subline
	1 - on the small line
	2 - on the middle of line
	3 - on the main line
	4 - in the lower subline (touch the main line)
	5 - out of line
        6 - dust found
***********************************************************/

 {
 INT mid,a,d;

 get_b_lines(c,&bl);
 mid=c->row+c->h/2;
 if (mid==bl.bm)
  return 2;
 if (mid<bl.bm)
  {
//  if (bl.n1>0 && mid+h/7<bl.b1 || c->row+c->h<=bl.b1)
  if (mid<bl.b1)    //Paul  04-10-96
           return 5;
  if (mid<bl.b2 || !fax1x2 && mid==bl.b2)
           return 0;
  if (c->row-(h+6)/12-fax1x2<=bl.b2 && c->row+c->h-1<=bl.bm)
   return 1;
  return 2;
  }
 else
  {
  if (c->row-h/8>=bl.b3 || bl.n3>=BASEOK && c->row>bl.b3)
   return 5;
  if (c->row<bl.b3)
   {
   if ((a=c->row-bl.bm)<0 && c->row+c->h<=bl.b3 ||
	a<(d=bl.b3-(c->row+c->h))-1 && d>2)
    return 2;
   if ((c->h<=3 || mid<bl.b3) &&
       (c->row+c->h-bl.b3<=1 ||
	c->row+c->h-bl.b3<=MAX(7*c->h/24,2) &&
	c->row+c->h-bl.b3<=bl.b3-c->row-2))
    return 3;
   }
  return 4;
  }
 }
///////////////////
static INT chkdotcom(INT h,INT dp,cell *c)
 {
 INT x,y,dt,cm,hc,wc,wm,i,j,k,ls,s;
 BYTE str[80];
 B_LINES bl;

 if (snap_activity('e'))
  {
  snap_show_text("check dotcom begin");
  snap_monitor();
  }
 get_b_lines(c,&bl);
 x=c->h-c->w;
 y=c->h+c->w;
 dt=cm=0;
 if (dp!=5 && !fax1x2 && c->h==1 && c->w>=3 ||
     dp==3 && 4*y<h && bl.b3-(c->row+c->h)>=MAX(2,c->h))
  goto ret;
 if (dp==5 ||
     5*y<=6*h &&
     2*c->w+((c->h==2 || dp==3)?1:0)>c->h+((fax1x2 && c->h>2)?2:0) &&
     (8*(x+((fax1x2)?3:0)+((c->cg_flag&c_cg_cutl)?2:0))>=-h ||
	 5*x>=-y || dp>=3 &&4*x>=-y || dp!=2 && c->h<=3 && c->w<=2*c->h) &&
     (x<=0 || ((!dp || dp==4)?8:5)*(x+((fax1x2)?1:0))<=h) &&
     (x<=0 || ((!dp || dp==4)?6:3)*x<=y) &&
     (dp!=2 || x+1+((fax1x2)?2:0)>=0 || c->w<=3) &&
     (c->h+((fax1x2)?2:0)>3 || dp!=4) &&
     (c->w<3 || c->h<2*c->w || c->row+c->h<=bl.b3) &&
     (!fax1x2 || dp!=4 || c->h<c->w))
  dt=1;
 if (dp!=5 && dp!=2 && (dp!=3 || c->row>=bl.bm-1) &&
     27*y>=8*h && 2*y<=3*h &&
     (x+((fax1x2)?3:0)>=((!dp || dp==4)?-1:0) &&
	      (c->h>=((fax1x2 || dp==4)?4:5) || dp<2) || x>0))
  cm=1;
 if (cm && dp<=1 && c->row>bl.b2)
  {cm=0; dt=1;}
 if (dt && cm)
  {
  if (rstr==NULL) rstr=save_raster(c);
  hc=c->h; wc=c->w;
  ls=(wc+7)>>3;
  if ((dp==4 || fax1x2 && dp==3 && -3*x<=2*c->h) && hc>=3)
   {
   for (j=0; !(rstr[j>>3]&(128>>(j%8))); j++) ;
   for (k=0; !(rstr[(hc-1)*ls+(k>>3)]&(128>>(k%8))); k++) ;
   for (s=0; !(rstr[(hc/2)*ls+(s>>3)]&(128>>(s%8))); s++) ;
   if (snap_activity('e'))
    {
    sprintf(str,"left abris: 0-%u,%u-%u,%u-%u",j,hc/2,s,hc-1,k);
    snap_show_text(str);
    snap_monitor();
    }
   if ((!j || !k) && s>=j && s>k)
    {dt=0; goto ret;}
   }
  for (wm=i=0; i<hc; i++)
   {
   for (j=0; !(rstr[i*ls+(j>>3)]&(128>>(j%8))); j++) ;
   for (k=wc-1; !(rstr[i*ls+(k>>3)]&(128>>(k%8))); k--) ;
   if (wm<(k-j+1)) wm=k-j+1;
   }
  if (snap_activity('e'))
   {
   sprintf(str,"max width = %u",wm);
   snap_show_text(str);
   snap_monitor();
   }
  if ((8*(hc-wm+((fax1x2)?1:0)+((!dp || dp==4)?1:0))>=h || 5*wm<=3*hc) &&
      wm<wc)
   dt=0;
  else
   {
   i=((2*hc+1)/3)*ls; if (hc<=4) i=(hc-1)*ls;
   for (j=0; !(rstr[i+(j>>3)]&(128>>(j%8))); j++) ;
   for (k=wc-1; !(rstr[i+(k>>3)]&(128>>(k%8))); k--) ;
   if (snap_activity('e'))
    {
    sprintf(str,"width on height %u = %u, left gap = %u",i/ls,k-j+1,j);
    snap_show_text(str);
    snap_monitor();
    }
   if (2*(k-j+1)<=wc || dp==4 && 7*(k-j+1)<=4*wc ||
       x+((fax1x2)?3:0)>1 && 4*(k-j+1)<=3*wc ||
       (dp==0 || dp==4) && 4*j>=wc && 4*(k-j+1)<=3*wc)
    {
    if (hc>4 || dp<2) dt=0;
    else
     {
     i=(hc-2)*ls;
     for (j=0; !(rstr[i+(j>>3)]&(128>>(j%8))); j++) ;
     for (k=wc-1; !(rstr[i+(k>>3)]&(128>>(k%8))); k--) ;
     if (snap_activity('e'))
      {
      sprintf(str,"width on height %u = %u",i/ls,k-j+1);
      snap_show_text(str);
      snap_monitor();
      }
     if (k-j+1<wc-1 || k-j+1==wc-1 && (hc>wc || dp==4))
      dt=0;
     }
    }
   else
    {
    if (dp>2)
     {
     if (dp==3 || x<=0) cm=0;
     }
    else
     {
     i=(hc/3)*ls; if (hc<=4) i=0;
     for (j=0; !(rstr[i+(j>>3)]&(128>>(j%8))); j++) ;
     for (k=wc-1; !(rstr[i+(k>>3)]&(128>>(k%8))); k--) ;
     if (snap_activity('e'))
      {
      sprintf(str,"width on height %u = %u, left gap = %u, right gap = %u",
	       i/ls,k-j+1,j,wc-k-1);
      snap_show_text(str);
      snap_monitor();
      }
     if (2*(k-j+1)<=wc+1 || x>1 && 4*(k-j+1)<3*wc ||
	 dp==0 && (4*j>=wc || 4*(wc-k-1)>=wc) && 4*(k-j+1)<3*wc)
      dt=0;
     else cm=0;
     }
    }
   }
  }
 if (dt && cm && (hc>=5 || fax1x2 && hc==4))
  {
  for (s=0,i=1; i<hc-1; i++,s+=k-j+1)
   {
   for (j=0; !(rstr[i*ls+(j>>3)]&(128>>(j%8))); j++) ;
   for (k=wc-1; !(rstr[i*ls+(k>>3)]&(128>>(k%8))); k--) ;
   }
  s=(s+(hc-2)/2)/(hc-2);
  if (snap_activity('e'))
   {
   sprintf(str,"average width = %u",s);
   snap_show_text(str);
   snap_monitor();
   }
  if ((6*(hc-s+((fax1x2 || !dp || dp==4)?1:0))<h && 5*s>3*hc) || s==wc)
   cm=0;
  }
ret:
 if (snap_activity('e'))
  {
  sprintf(str,"check dotcom : %s",
		       (dt)?((cm)?"both":"point"):((cm)?"comma":"none"));
  snap_show_text(str);
  snap_monitor();
  }
 return (dt+(cm<<1));
 }

static INT chkdash(INT h,INT dp,cell *c)
 {
 INT r;
 BYTE str[80];

 r=(dp<=3 && /*9*(c->h)<=4*h*/27*c->h<=13*h && c->w>=MIN(4,h/3) &&
    (5*(c->w)>=2*h || dp==2 && c->w>c->h))?1:0;

 if (snap_activity('e'))
  {
  sprintf(str,"check dash : %s",(r)?"yes":"no");
  snap_show_text(str);
  snap_monitor();
  }
 return r;
 }

static INT chkquot(INT h,INT dp,cell *c)
 {
 WORD ls,i,j,k,i1,j1,k1,min,l,s,r,lu,ru,ld,rd;
 BYTE str[80];

 if (snap_activity('e'))
  {
  snap_show_text("check quotes begin");
  snap_monitor();
  }
 r=0;
 if ((dp<=1 || dp==4) && 3*(c->h)>=h && 4*(c->w)>=h && (c->w)<=h)
  {
  if (rstr==NULL) rstr=save_raster(c);
  ls=(c->w+7)>>3;
  for (min=c->h+1,i1=(c->w)/2-1; i1<=(c->w)/2+1; i1++)
   {
   s=i1/8; l=128>>(i1%8);

   for (j1=0; !(rstr[j1*ls+s]&l); j1++) ;

   for (k1=c->h-1; !(rstr[k1*ls+s]&l); k1--)                  // AK add c/g 06.03.98
	if ( k1 == 0 )
		break;

   if (k1-j1+1<min)
    {
    min=k1-j1+1;
    i=i1; j=j1; k=k1;
    }
   }
  if (snap_activity('e'))
   {
   sprintf(str,"height in the middle (%u) = %u",i,min);
   snap_show_text(str);
   snap_monitor();
   }
  if (min<c->h && 14*min<=11*((c->h)+((fax1x2)?2:0)))
   {
   j1=j; k1=k;
   if (j) j--;
   if (k<c->h-1) k++;
   lu=rstr[j*ls+((c->w)>>5)]&(128>>(((c->w)>>2)%8));
   ru=rstr[j*ls+((3*(c->w))>>5)]&(128>>(((3*(c->w))>>2)%8));
   ld=rstr[k*ls+((c->w)>>5)]&(128>>(((c->w)>>2)%8));
   rd=rstr[k*ls+((3*(c->w))>>5)]&(128>>(((3*(c->w))>>2)%8));
   if (snap_activity('e'))
    {
    sprintf(str,"korners : lt=%u,rt=%u,lb=%u,rb=%u",lu,ru,ld,rd);
    snap_show_text(str);
    snap_monitor();
    }
   if (j1 && lu && ru || c->h-1-k1 && ld && rd)
    r=1;
   }
  }
 if (snap_activity('e'))
  {
  sprintf(str,"check quotes : %s",(r)?((dp<=1)?"upper":"lower"):"no");
  snap_show_text(str);
  snap_monitor();
  }
 return(r);
 }

static INT chkstar(INT h,INT dp,cell *c)
 {
 INT ls,i,j,l,r,x,y,n,p;
 BYTE str[80];

 if (snap_activity('e'))
  {
  snap_show_text("check star begin");
  snap_monitor();
  }
 r=0;
 x=c->h-c->w; y=c->h+c->w;
 if (dp>2 || x>h/5 || x<-h/7 || 3*y<2*h) goto ret;
 if (rstr==NULL) rstr=save_raster(c);
 ls=(c->w+7)>>3;
 i=(c->w)>>4; l=128>>(((c->w)>>1)%8);
 for (x=j=0; j<c->h; j++) if (rstr[j*ls+i]&l) x++;
 if (snap_activity('e'))
  {
  sprintf(str,"height in the middle = %u",x);
  snap_show_text(str);
  snap_monitor();
  }
 if (x<c->h-2) goto ret;
 j=((c->h)/2)*ls;
 for (n=p=x=i=0; i<c->w; i++)
  if (rstr[j+(i>>3)]&(128>>(i%8)))
   {
   x++;
   if (!p) {n++; p=1;}
   }
  else p=0;
 if (snap_activity('e'))
  {
  sprintf(str,"width in the middle = %u, intersection number = %u",x,n);
  snap_show_text(str);
  snap_monitor();
  }
 if (n!=1 || x>2*c->w/3) goto ret;
 for (n=p=j=0; j<c->h; j++)
  if (rstr[j*ls]&64)
   {if (!p) {n++; p=1;}}
  else p=0;
 if (n!=2)
  for (n=p=j=0; j<c->h; j++)
   if (rstr[j*ls]&64)
    {if (!p) {n++; p=1;}}
   else p=0;
 if (snap_activity('e'))
  {
  sprintf(str,"left  intersection number=%u",n);
  snap_show_text(str);
  snap_monitor();
  }
 if (n!=2) goto ret;
 i=(c->w-1)/8; l=128>>((c->w-1)%8);
 for (n=p=j=0; j<c->h; j++)
  if (rstr[j*ls+i]&l)
   {if (!p) {n++; p=1;}}
  else p=0;
 if (n!=2)
  {
  i=(c->w-2)/8; l=128>>((c->w-2)%8);
  for (n=p=j=0; j<c->h; j++)
   if (rstr[j*ls+i]&l)
    {if (!p) {n++; p=1;}}
   else p=0;
  }
 if (snap_activity('e'))
  {
  sprintf(str,"right intersection number=%u",n);
  snap_show_text(str);
  snap_monitor();
  }
 if (n==2) r=1;
ret:
 if (snap_activity('e'))
  {
  sprintf(str,"check star : %s",(r)?"yes":"no");
  snap_show_text(str);
  snap_monitor();
  }
 return(r);
 }

static INT chkplus(INT h,INT dp,cell *c)
 {
 INT ls,i,j,l,r,x,y,lu,ru,ld,rd;
 BYTE str[80];

 if (snap_activity('e'))
  {
  snap_show_text("check plus begin");
  snap_monitor();
  }
 r=0;
 x=c->h-c->w; y=c->h+c->w;
 if (dp<=2 && x<=h/8 && x>=-h/8 && y>=h)
  {
  if (rstr==NULL) rstr=save_raster(c);
  ls=(c->w+7)>>3;
  i=(c->w)>>4; l=128>>(((c->w)>>1)%8);
  for (x=j=0; j<c->h; j++) if (rstr[j*ls+i]&l) x++;
  if (snap_activity('e'))
   {
   sprintf(str,"height in the middle = %u",x);
   snap_show_text(str);
   snap_monitor();
   }
  if (x>=c->h-2)
   {
   j=((c->h)/2)*ls;
   for (x=i=0; i<c->w; i++) if (rstr[j+(i>>3)]&(128>>(i%8))) x++;
   if (snap_activity('e'))
    {
    sprintf(str,"width in the middle = %u",x);
    snap_show_text(str);
    snap_monitor();
    }
   if (x>=c->h-2)
    {
    lu=rstr[((c->h)/4)*ls+(((c->w)/4)>>3)]&(128>>((c->w)/4)%8);
    ru=rstr[((c->h)/4)*ls+(((3*(c->w))/4)>>3)]&(128>>((3*(c->w))/4)%8);
    ld=rstr[((3*(c->h))/4)*ls+(((c->w)/4)>>3)]&(128>>((c->w)/4)%8);
    rd=rstr[((3*(c->h))/4)*ls+(((3*(c->w))/4)>>3)]&(128>>((3*(c->w))/4)%8);
    if (snap_activity('e'))
     {
     sprintf(str,"korners : lt=%u,rt=%u,lb=%u,rb=%u",lu,ru,ld,rd);
     snap_show_text(str);
     snap_monitor();
     }
    if (!(lu|ru|ld|rd))
     r=1;
    }
   }
  }
 if (snap_activity('e'))
  {
  sprintf(str,"check plus : %s",(r)?"yes":"no");
  snap_show_text(str);
  snap_monitor();
  }
 return(r);
 }

static INT chkslash(INT h,INT dp,cell *c)
 {
 INT r,ls,i,j,s;
 BYTE str[80];

 r=0;
 if ((dp==1 || dp==2) && c->h>=4 && c->h>=h/2-2 && c->w>=h-2)
  {
  if (rstr==NULL)
   rstr=save_raster(c);
  ls=(c->w+7)>>3;
  for (s=i=0; i<c->h; i++)
   {
   j=c->w-1-(c->w-1)*i/(c->h-1);
   if (rstr[ls*i+j/8]&(128>>(j%8))) s++;
   }
  if (s>=c->h-2 && !(rstr[ls]&(128>>1)) &&
      !(rstr[ls*(c->h-2)+(c->w-2)/8]&(128>>((c->w-2)%8))))
   r=1;
  }
 if (snap_activity('e'))
  {
  sprintf(str,"check slash : %s",(r)?"yes":"no");
  snap_show_text(str);
  snap_monitor();
  }
 return r;
 }

static INT chkcircle(INT h,INT dp,cell *c)
 {
 INT r,i;
 BYTE flgsv,str[80];

 r=0;
 if (dp<4 && c->h>=h/2-1)
  {
  flgsv=(BYTE)c->flg;
  short_recog_cell(c);
  c->flg=flgsv;
  for (i=0; i<c->nvers; i++)
   if (c->vers[i].let=='o')
    {r=1; break;}
  }
 if (snap_activity('e'))
  {
  sprintf(str,"check circle : %s",(r)?"yes":"no");
  snap_show_text(str);
  snap_monitor();
  }
 return r;
 }

static INT chkquock(INT h,INT dp,cell *c)
 {
 INT r,sl,sr,i,j,l;
 BYTE str[80];

 r=0;
 if (dp==2 && 11*c->h>=4*h && c->h>=c->w)
  {
  if (rstr==NULL)
   rstr=save_raster(c);
  l=(c->w+7)>>3;
  for (sl=sr=i=0; i<c->h/3; i++)
   {
   for (j=0; j<c->w/2; j++)
    if (rstr[i*l+j/8]&(128>>(j%8)))
     sr++;
   for (j=(c->w+1)/2; j<c->w; j++)
    if (rstr[i*l+j/8]&(128>>(j%8)))
     sl++;
   }
  for (i=c->h/3; i<c->h-c->h/3; i++)
   {
   for (j=0; j<c->w/2; j++)
    if (rstr[i*l+j/8]&(128>>(j%8)))
     sl++;
   for (j=(c->w+1)/2; j<c->w; j++)
    if (rstr[i*l+j/8]&(128>>(j%8)))
     sr++;
   }
  for (i=c->h-c->h/3; i<c->h; i++)
   {
   for (j=0; j<c->w/2; j++)
    if (rstr[i*l+j/8]&(128>>(j%8)))
     sr++;
   for (j=(c->w+1)/2; j<c->w; j++)
    if (rstr[i*l+j/8]&(128>>(j%8)))
     sl++;
   }
  if (sr-sl>=sr/2 || 2*c->h>=3*c->w && sr-sl>=sr/3 ||
		     c->h>=2*c->w && sr-sl>=MAX(3,sr/4))
   r=1;
  else
   if (sl-sr>=sl/2 || 2*c->h>=3*c->w && sl-sr>=sl/3 ||
		      c->h>=2*c->w && sl-sr>=MAX(3,sr/4))
    r=-1;
  }
 if (snap_activity('e'))
  {
  sprintf(str,"check quocket : %s",(r)?((r>0)?"right":"left"):"no");
  snap_show_text(str);
  snap_monitor();
  }
 return r;
 }

INT chkquocks2(cell*c,PBYTE r,INT h,INT w,INT d);
static INT chkquocks(INT h,INT dp,cell *c)
 {
 INT i,di,i1,i2,j,j1,j2,l,d,r;
 BYTE str[80];

 d=0;
 if (dp==2 && 11*c->h>=4*h && 3*c->w>=2*c->h &&
     c->w <=3*c->h ) // Pit 05-30-94 12:00pm
  {
  if (rstr==NULL)
   rstr=save_raster(c);
  l=(c->w+7)>>3;
  i=(c->h/2)*l;
  for (d=di=0; ; )
   {
   for (j1=0; !(rstr[i+di+j1/8]&(128>>(j1%8))); j1++) ;
   for (j2=c->w-1; !(rstr[i+di+j2/8]&(128>>(j2%8))); j2--) ;
   j2=c->w-1-j2;
   if (j1<=1 && j2>j1)
    {j=c->w-1-(5*c->w)/17; d=-1; break;}
   if (j2<=1 && j1>j2)
    {j=(5*c->w)/17; d=1; break;}
   if (!di)
    di=-l;
   else
    {
    if (di<0)
     di=l;
    else
     goto ret;
    }
   }
   if(chkquocks2(c,rstr,c->h,c->w,d)) goto ret;
{
extern BYTE multy_language;
   // >> similar з , << similar Є,­
   if( multy_language && d!=0 && c->h>12 )
    {
    INT ii,jj,ll;
    if( d>0 && j1*8<c->w )
      {
      d=0;
      goto ret;
      }
    if( d>0 )
      {
      for (ll=0,ii=1; ii<c->h-1; ii++)
        {
        for (jj=c->w-1; !(rstr[l*ii+jj/8]&(128>>(jj%8))); jj--) ;
        jj = (c->w-1-jj);
        if( ll<jj ) ll=jj;
        }
      }
    if( d<0 )
      {
      for (ll=0,ii=1; ii<c->h-1; ii++)
        {
        for(jj=0;!(rstr[l*ii+jj/8]&(128>>(jj%8)));jj++);
        if( ll<jj ) ll=jj;
        }
      }
    if( ll<3 )
      {
      d=0;
      goto ret;
      }
    }
}
  for (r=0; r<=2; r++,j+=d)
   {
   for (i1=0; !(rstr[l*i1+j/8]&(128>>(j%8))); i1++) ;
   for (i2=c->h-1; !(rstr[l*i2+j/8]&(128>>(j%8))); i2--) ;
   i2=c->h-1-i2;
   if (i1 && i2 && i1+i2>=MAX(2,c->h/5))
    {
    for (j1=j; j1>=0 && !(rstr[l*(i1-1)+j1/8]&(128>>(j1%8))); j1--) ;
    for (j2=j; j2<c->w && !(rstr[l*(i1-1)+j2/8]&(128>>(j2%8))); j2++) ;
    if (j1<0 || j2==c->w)
     continue;
    for (j1=j; j1>=0 && !(rstr[l*(c->h-i2)+j1/8]&(128>>(j1%8))); j1--) ;
    for (j2=j; j2<c->w && !(rstr[l*(c->h-i2)+j2/8]&(128>>(j2%8))); j2++) ;
    if (j1<0 || j2==c->w)
     continue;
    break;
    }
   }
  if (r>2)
   {d=0; goto ret;}
  r=MAX(1,c->h/6);
  for (i=r,j1=(d<0)?0:c->w-1; !(rstr[l*i+j1/8]&(128>>(j1%8))); j1-=d) ;
  for (i=c->h-1-r,j2=(d<0)?0:c->w-1; !(rstr[l*i+j2/8]&(128>>(j2%8)));
								     j2-=d) ;
  if (d>0)
   {j1=c->w-1-j1; j2=c->w-1-j2;}
  if (j1<MIN(1,c->w/6) || j2<MIN(1,c->w/6))
   d=0;
  }
ret:
 if (db_status)
  snap_newcell(c);
 if (snap_activity('e'))
  {
  sprintf(str,"check quockets : %s",(d)?((d>0)?"right":"left"):"no");
  snap_show_text(str);
  snap_monitor();
  }
 return d;
 }

static void dust_to_bad(cell *c)
 {
 INT i;
 cell *c1;

 if (db_status)
  snap_newcell(c);
 short_recog_cell(c);
 levcut(c,1);
 for (i=0; i<c->nvers; i++)
  if (c->vers[i].let=='i') break;
 if (i<c->nvers)
  {
  if (snap_activity('e'))
   {
   snap_show_text("dust to i");
   snap_monitor();
   }
  c->nvers=1;
  c->vers[0].let='i';
  c->vers[0].prob=128;
  c->vers[1].let=0;
  }
 else
  {
  if (snap_activity('e'))
   {
   snap_show_text("dust to bad");
   snap_monitor();
   }
  set_bad_cell(c);
  }
 for (c1=c->prev;
	    !(c1->flg&(c_f_let|c_f_bad|c_f_fict)) || c1->flg&c_f_punct;
							      c1=c1->prev) ;
 c1->nextl->prevl=c;
 c->nextl=c1->nextl;
 c1->nextl=c;
 c->prevl=c1;
 }

static void intval(cell *c,cell *cb)
 {
 cell *c1,*c2,*c3,/* *sav1,*sav2, */ *cbb;
 BYTE l1,l2,l3;
 INT fe,fm;
 INT h,d,max,s,hh,ww;

 cbb=cb->prev;
 for (c1=cbb->next; c1!=c; c1=c1->next)
  {
  if (!(c1->flg&c_f_punct)
      || c1->cg_flag&c_cg_comp)  //Paul 07-10-96
   continue;
  get_b_lines(c1,&bl);
  h=bl.ps;
  l1=c1->vers[0].let;
  fe=fm=0;
  c2=c1->next;
  if (db_status) snap_newcell(c1);
  if (snap_activity('e'))
   {
   snap_show_text("pairing");
   snap_monitor();
   }
  if (c2==c)
   fe=1;
  else
   {
   fm=1;
   l2=c2->vers[0].let;
   if ((l1==':' || l1=='-' || l1=='_') &&
       (l2==':' || l2=='-' || l2=='_') &&
       c2->col-(c1->col+c1->w)<=MAX(3,h/5) &&
       abs(c1->row-c2->row)<=1 &&
       abs(c1->row+c1->h-(c2->row+c2->h))<=1 &&
       //!line_tabcell &&
       (d=dustpos(h,c1))>=0 && d<=3 &&
       MIN(c1->row,c2->row)>bl.b1)
    {
    hh=MAX(c2->row+c2->h,c1->row+c1->h)-MIN(c2->row,c1->row);
    ww=MAX(c2->col+c2->w,c1->col+c1->w)-MIN(c2->col,c1->col);
    if (ww<h || 9*hh>2*ww || pitchsize && ww<=3*pitchsize/2)
     c2->vers[0].let='-';
    else
     {
     if (6*ww>7*h || 9*hh<ww)
      c2->vers[0].let='_';
     else
      {
      if (((c3=c1->prev)->prev==NULL || c1->col-c3->col-c3->w>=h/2) &&
	  ((c3=c2->next)->next==NULL || c3->col-c2->col-c2->w>=h/2))
       c2->vers[0].let='_';
      else
       c2->vers[0].let='-';
      }
     }
    }
   else
    {
    if ((l1==0x27 || l1==':') && (l2==0x27 || l2==':') &&
	MAX(c1->h,c2->h)>=h/5 &&
	(d=c2->col-c1->col-c1->w)<=h/2 &&
	c1->row+c1->h>c2->row && c2->row+c2->h>c1->row &&
	((c3=c2->next)==c || (l3=c3->vers[0].let)!=0x27 && l3!=':' ||
	 d<=c3->col-c2->col-c2->w))
     {
     if (abs(c1->h-c2->h)<=MAX(2,MAX(c1->h,c2->h)/3))
      c2->vers[0].let='"';
     else
      {
/*      if (c1->h>c2->h)
       {
       sav1=c2->next; sav2=c2->prev;
       memcpy(c2,c1,sizeof(cell));
       c2->next=sav1; c2->prev=sav2;
       }   */
      c2->vers[0].let=0x27;
      }
     }
    else
     {
     if (l1==',' && l2==',' && abs(c1->h-c2->h)<=(c1->h+c2->h)/4 &&
	 abs(c1->row+c1->h/2-(c2->row+c2->h/2))<=h/4 &&
	 c2->col-(c1->col+c1->w)<=h/2 && !line_tabcell)
      c2->vers[0].let=low_quotes;	// Макрос 31.05.2001 E.P.
     else
      {
      if ((l1=='/' && (l2==0x27 || l2==':' || l2=='O') ||
	  (l1==0x27 || l1==':' || l1=='O') && l2=='/') &&
	   (c3=c2->next)!=c && ((l3=c3->vers[0].let)=='o' || l3=='.'))
       {c2->vers[0].let='%'; fm=2;}
      else
       {
       if (l1=='-' && l2=='-' &&
	  abs(c1->col+c1->w/2-(c2->col+c2->w/2))<(c1->w+c2->w)/8)
	c2->vers[0].let='=';
       else
	{
	if ((l1=='<' || l1=='>') && l2==l1)
	 c2->vers[0].let=(l1=='<')?left_quocket:right_quocket;
	else
	 {
	 if (c1->col+MAX(3,c1->w)+((italic && c1->row>c2->row)?3:0)<c2->col
	     || MIN(c1->row,c2->row)<
			     cbb->row-((fax1x2)?3:2)-((pitchsize)?1:0) &&
		MAX(c1->row,c2->row)>=bl.bm
	      /*|| (d=c1->row-c2->row)<=4 && d>=-4*/)
	  {fe=1; fm=0;}
	 else
	  {
	  if (((l1==':' || l1=='-' || l1==0x27 && 7*(c1->h-c1->w)<=h &&
		  (abs(c1->h+c1->w-(c2->h+c2->w))<=3 || dustpos(h,c1)) ||
						   fax1x2 && l1=='=') &&
	       (l2=='.' && c2->row<bl.b3 ||
		  (l2==':' || fax1x2 && l2=='=') && dustpos(h,c2)>=2 ||
		  l2==',' && abs(c1->h+c1->w-(c2->h+c2->w))<=3 &&
						  c2->row+c2->h<=bl.b3) ||
	       (l2==':' || l2=='-' || l2==0x27 && 7*(c2->h-c2->w)<=h &&
		  (abs(c1->h+c1->w-(c2->h+c2->w))<=3 || dustpos(h,c2)) ||
						   fax1x2 && l2=='=') &&
	       (l1=='.' && c1->row<bl.b3 ||
		  (l1==':' || fax1x2 && l1=='=') && dustpos(h,c1)>=2 ||
		  l1==',' && abs(c1->h+c1->w-(c2->h+c2->w))<=3 &&
						  c1->row+c1->h<=bl.b3)) &&
	      (abs(c1->h-c2->h)<=2 ||
				   2*c1->h<=3*c2->h && 2*c2->h<=3*c1->h) &&
	      (abs(c1->w-c2->w)<=2 ||
				   2*c1->w<=3*c2->w && 2*c2->w<=3*c1->w) &&
	      (c1->row>=c2->row || c2->col+c2->w/2-(c1->col+c1->w/2)<=
						  MAX(2,MIN(c1->w,c2->w)/2)))
	   {
	   c2->vers[0].let=':';
	   if (c1->nvers==2 || c2->nvers==2 || l1==',' || l2==',')
	    {
	    if (c1->nvers==2 && c1->vers[0].let=='.' ||
		c2->nvers==2 && c2->vers[0].let==',' || l1==',' || l2==',')
	     c2->vers[1].let=';';
	    else
	     {c2->vers[0].let=';'; c2->vers[1].let=':';}
	    c2->vers[1].prob=254;
	    c2->vers[2].let=0;
	    c2->nvers=2;
	    }
	   }
	  else
	   {
	   if (((l1==':' || l1=='-' && 2*c1->h>=c1->w ||
		 l1==0x27 && 7*(c1->h-c1->w)<=h ||
		 fax1x2 && l1=='=') && c1->row<=bl.bm &&
		(l2==',' || l2=='.' && dustpos(h,c2)==3 && c2->h>c1->h) ||
		(l2==':' || l2=='-' ||
		 l2==0x27 && 7*(c2->h-c2->w)<=h ||
		 fax1x2 && l2=='=') && c2->row<=bl.bm &&
		(l1==',' || l1=='.' && dustpos(h,c1)==3 && c1->h>c2->h)))
	    {
	    if (abs(c1->w-c2->w)<=3 ||
		c1->row<c2->row && 5*c1->w>=2*c2->w ||
		c2->row<c1->row && 5*c2->w>=2*c1->w)
	     c2->vers[0].let=';';
	    else
	     {fe=1; fm=0;}
	    }
	   else
	    {
	    if ((l1=='-' || l1=='_' || l1=='=') &&
		(l2=='-' || l2=='_' || l2=='='))
	     {
	     if (MAX(c1->row,c2->row)-MIN(c1->row+c1->h,c2->row+c2->h)<=h/2)
	      c2->vers[0].let='=';
	     else
	      c2->vers[0].let=':';
	     }
	    else
	     {
	     if (l1=='.' && l2=='.')
	      c2->vers[0].let=',';
	     else
	      {
	      if ((l1==':' || l1==0x27) && (l2==':' || l2==0x27))
	       c2->vers[0].let=0x27;
	      else
	       {fe=1; fm=0;}
	      }
	     }
	    }
	   }
	  }
	 }
	}
       }
      }
     }
    }
   }

  if (fe && (memchr(".:=><Oo",l1,6) || l1==0x27 || l1=='/'))
   {
   if (l1==':' && c1->h+c1->w>h/3)
    {
    d=dustpos(h,c1);
    if (!pitchsize && d==2 && c1->w<=c1->h+1 &&
    MAX(c1->w,c1->h)>bl.ps/3 && //Oleg
	((c3=c1->prev)->prev==NULL || c1->col-c3->col-c3->w>=h/2) &&
	((c3=c1->next)->next==NULL || c3->col-c1->col-c1->w>=h/2))
     {
     c1->vers[0].let=liga_bull;
     c1->vers[0].prob=150;
     }
    else
     {
     if ((d==2 || d==1 && c1->row>bl.b2) &&
	 bl.b3-(c1->row+c1->h)>=3 && (bl.n2>0 || c1->row<=bl.bm) &&
	 c1->w+((c1->next->flg&c_f_fict)?1:0)>c1->h+((fax1x2)?2:0))
      {
      c1->vers[0].let=c1->h>c1->w+1?'-':'.'; // Oleg
      c1->vers[0].prob=150;
      }
     else
      {
      if (d>2 ||
	  d==2 && c1->row+c1->h/2>bl.bm && !(c1->cg_flag&c_cg_cut) &&
	  (c1->row>bl.bm+1 || c1->row+c1->h+MAX(2,bl.ps/6)>=bl.b3) ||
	  d<2 && c1->row<bl.b2 && c1->h+((fax1x2)?2:0)>=c1->w &&
							   c1->h>=bl.ps/4)
       {
       c1->vers[0].let=(d<2)?0x27:'.';
       c1->vers[0].prob=150;
       }
      else
       {
       if (c1->flg&c_f_bad)
	dust_to_bad(c1);
       else
	{
	no_cut(c1);
    c1=hide(c1);
	}
       }
      }
     }
    }
   else
    {
    if (l1=='=' && dustpos(h,c1)==3 && c1->row+c1->h/2<=bl.b3-bl.ps/3)
     {
     if (c1->w<h || 9*c1->h>2*c1->w || pitchsize && c1->w<=3*pitchsize/2)
      c1->vers[0].let='-';
     else
      {
      if (11*c1->w>12*h || 9*c1->h<c1->w)
       c1->vers[0].let='_';
      else
       {
       if (((c3=c1->prev)->prev==NULL || c1->col-c3->col-c3->w>=h/2) &&
	   ((c3=c1->next)->next==NULL || c3->col-c1->col-c1->w>=h/2))
	c1->vers[0].let='_';
       else
	c1->vers[0].let='-';
       }
      }
     c1->vers[0].prob=150;
     }
    else
     {
     if ((l1=='<' || l1=='>') &&
	 ((c3=c1->prev)->vers[0].let==l1 &&
	     c1->col-(c3->col+c3->w)<=(c1->w+c3->w)/4 ||
	  (c3=c1->next)->vers[0].let==l1 &&
	     c3->col-(c1->col+c1->w)<=(c1->w+c3->w)/4))
      {
      cell *cp;  // AL 940320
      c3->vers[0].let=(l1=='<')?left_quocket:right_quocket;
      c3->vers[0].prob=254;
      c3->vers[1].let=0;
      c3->nvers=1;
      if (c3->flg&c_f_bad)
       c3->flg=c_f_let;
      cp = c1->prev;  // AL 940320
      clist[0]=c1;
      clist[1]=c3;
      compose_cell(2,clist,c3);
      if( c3->nextl==(cell *)0xffff0000 && c3->nextl==(cell *)0xffff0000 )
        c3->flg=c_f_punct;
      c3->left=c3->col;
      c3->right=c3->col+c3->w;
      //c1=c1->prev;
      c1=cp; // AL 940320
      }
     else
      {
      if ((l1!=0x27 || c1->row>=bl.b2) && (l1!='.' || c1->row>bl.b3))
       {
       if (c1->flg&c_f_bad)
	dust_to_bad(c1);
       else
	{
	no_cut(c1);
    c1=hide(c1);
	}
       }
      }
     }
    }
   }

  if (fm)
  {
       clist[0]=c1;
       clist[1]=c2;
       if( fm==2 ) // Oleg & Pit : 13-07-1999 : Check non init pointer
        clist[2]=c3;
       no_cut(c1);
       if (fm==2)
        no_cut(c3);
       // AL OK
       compose_cell((INT)(fm+1),clist,c2);
       c2->left=c2->col;
       c2->right=c2->col+c2->w;
       c1=c2;
       if (db_status)
           snap_newcell(c1);
       if (snap_activity('e'))
       {
           snap_show_text("pairing OK");
           snap_monitor();
       }
  }
  }

 for (c1=cbb->next; c1!=c; c1=c1->next)
  {
      get_b_lines(c1,&bl);
      h=bl.ps;
      if (((l1=c1->vers[0].let)==':' || l1==';') &&
          (c2=c1->next)!=c && c2->vers[0].let==0x27 &&
          c2->col-c1->col-c1->w<=h/2)
       {
          c2->vers[0].let='"';
          for (d=0; d<c1->nvers; d++)
          {
              if (c1->vers[d].let==':') c1->vers[d].let='.';
              if (c1->vers[d].let==';') c1->vers[d].let=',';
          }
          c1->env=c2->env=NULL;
       }
  }

 for (c1=cbb->next; c1!=c; c1=c1->next)
  if (((l1=c1->vers[0].let)=='.' || l1==',') &&
      (c2=c1->next)!=c &&
      ((l2=c2->vers[0].let)=='.' || l2==',') &&
      (c3=c2->next)!=c &&
      ((l3=c3->vers[0].let)=='.' || l3==',') &&
      c1->prev->vers[0].let!='.' &&
      !(l1==',' && c3->next->vers[0].let=='.'))
   {
   if ((max=MAX(c1->h,MAX(c2->h,c3->h)))-MIN(c1->h,MIN(c2->h,c3->h))<=
					      (s=(c1->h+c2->h+c3->h)/6))
    {
         c1->vers[0].let='.';
         c2->vers[0].let='.';
         c3->vers[0].let='.';
    }
   else
    {    cell *cc1;   // AL 940320
         cc1=c1->prev;
         if (c1->h<max-s)
         hide(c1);
         if (c2->h<max-s)
         hide(c2);
         if (c3->h<max-s)
         hide(c3);
         c1 = cc1; // AL
    }
   }

 for (c1=cbb->next; c1!=c; c1=c1->next)
  {
  get_b_lines(c1,&bl);
  h=bl.ps;
  if (c1->vers[0].let==0x27 &&
      (c2=c1->next)!=c && c2->vers[0].let==0x27 &&
      c2->col-c1->col-c1->w<=h/2 &&
      c1->row+c1->h>c2->row && c2->row+c2->h>c1->row)
   {
   c1->vers[0].let='"';
   clist[0]=c1;
   clist[1]=c2;
   // AL OK
   compose_cell(2,clist,c1);
   c1->left=c1->col;
   c1->right=c1->col+c1->w;;
   }
  }

 for (c1=cbb->next; c1!=c; c1=c1->next)
  {
  get_b_lines(c1,&bl);
  h=bl.ps;
  if (c1->vers[0].let==0x27 &&
      (c2=c1->next)!=c && ((l2=c2->vers[0].let)=='.' || l2==',') &&
      (c3=c2->next)!=c && c3->vers[0].let==0x27 &&
      c3->col-c1->col-c1->w<=h/2 &&
      c1->row+c1->h>c3->row && c3->row+c3->h>c1->row)
   {
   clist[0]=c1;
   clist[1]=c3;
   if (c2->col+c2->w/2>(c1->col+c3->col+c3->w)/2)
    {
    c1->vers[0].let='"';
    // AL OK
    compose_cell(2,clist,c1);
    c1->left=c1->col;
    c1->right=c1->col+c1->w;
    }
   else
    {
    cell *cp;   // AL 940320
    cp=c1->prev;
    c3->vers[0].let='"';
    compose_cell(2,clist,c3);
    c3->left=c3->col;
    c3->right=c3->col+c3->w;
    //c1=c1->prev->next;
    c1=cp->next;
    }
   }
  }

 for (c1=cbb->next; c1!=c; c1=c1->next)
  if (c1->flg==(c_f_punct|c_f_bad))
   c1->flg=c_f_punct;
 }

static void no_cut(cell *c)
 {

 if (c->cg_flag&c_cg_cutl)
  (c->prev)->cg_flag-=(c->prev)->cg_flag&c_cg_cutr;
 if (c->cg_flag&c_cg_cutr)
  (c->next)->cg_flag-=(c->next)->cg_flag&c_cg_cutl;
 }

void clean_punct_temp()
{
cell *C=cell_f()->next;
for (; C->next; C=C->next)
    {
    if( (C->flg_new&c_fn_temp) &&
        (C->flg & (c_f_punct|c_f_let)) &&
         C->nvers && C->vers[0].prob>100 )
        C->flg_new -= c_fn_temp;
    }

return;
}

void clean_punct()
{
  cell *L,*R,*C=cell_f()->next;
  CHAR str[80];
  INT gap=get_gap();

  for (; C->next; C=C->next)
  {
    if (!(C->flg & c_f_punct))
        continue;
    if (C->vers[0].let=='\'' && language == LANG_ENGLISH)
        continue;
    for (L=C; L->prev && !(L->flg & (c_f_let+c_f_bad)); L=L->prev);
    if (!(L->flg & (c_f_let+c_f_bad)))
        continue;
    R=L->nextl;
    if (!(R->flg & (c_f_let+c_f_bad)))
        continue;
    if (R->col - (L->col+L->w) <= gap )
    {
      if (snap_activity('f'))
        {
        sprintf(str,"too closed - delete");
        snap_show_text(str);
        snap_newcell(C);
        snap_monitor();
        }
      C=hide(C);
    }
  }
}

void clean_line()
{
  cell *B,*C=cell_f()->next;

  while (C->next)
  {
    if (C->flg&c_f_dust)
      C=del_cell(C);
    else
    if (C->flg&c_f_punct && strchr(".,-",C->vers[0].let))
    {
      B=C;
      while (B->next && !(B->flg & (c_f_let | c_f_bad)))  B=B->next;
      if (B->flg & (c_f_let | c_f_bad) && contain(B,C))  C=del_cell(C);
    }
    C=C->next;
  }
}

static INT contain(cell *new, cell *old)
//
//	This procedure check whether new cell contains old one.
//
 {

 if (new->r_col >= old->r_col)
  return 0;
 if (new->r_col+new->w <= old->r_col+old->w)
  return 0;
 if (new->r_row >= old->r_row)
  return 0;
 if (new->r_row+new->h <= old->r_row+old->h)
  return 0;
 return 1;
 }
/////////////////////////////////////////////////////////////////////////////////////////////
// AK change at 19.03.98
cell *hide(cell *C)
{
	cell *B=C;

	if (language == LANG_RUSSIAN)
	{
		C=C->prev;

		if (B->flg & c_f_punct)
			B->flg ^= c_f_dust | c_f_punct;

		B->complist=(c_comp *)sv_fantom;
		sv_fantom=del_save_cell(B);
	}
	else
		C=del_cell(C);

	return C;
}
///////////////////////////////////////////////////////////////////////////////////////////
void hide_dusts(BYTE mode)
{
	cell *C;

	for (C=cell_f()->next; C && C != cell_l()/*C->next*/; C=C->next)
		if (C->flg&c_f_dust && !(mode && C->cg_flag&c_cg_cut))
		{
			C=hide(C);
		}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void recover_dusts()
{
  cell *B=cell_l();
return;
  while (sv_fantom)
  {
    B=rest_cell(sv_fantom,B);
    sv_fantom=(PBYTE)(B->complist);
  }
}
void clear_twin_flags(void)
{
cell *c,*e;

for(c=cell_f()->next, e=cell_l(); c!=e; c=c->next )
    {
    if( c->flg!=c_f_bad && (c->flg&c_f_bad)!=0 &&
        c->flg!=(c_f_bad|c_f_solid) && c->flg&(c_f_bad|c_f_solid)!=0 )
        dust_to_bad(c);
    }
return;
}
//*******************************************************************
void czech_dt_glue_apostroph()
{
// ACC_ROOF_INF над d,t в Чешском похож на апостроф. 07.09.2000 E.P.

 cell *c,*cc;
 BYTE let;
 INT gap=get_gap();
 INT d;

for (c=(cell_f())->next; (cc=c->next)!=NULL; c=c->next)
	{
	c->left=c->col;
	c->right=c->col+c->w;

	if (c->flg&(c_f_dust|c_f_punct))
		continue;

	get_b_lines(c,&bl);
	let=c->vers[0].let;

	if (let != 'd' && let != 't')
		continue;

	// Апостроф после d, t
	if (cc->vers[0].let != '\'')
		continue;

	// Достаточно ли близко
	d= cc->col - c->right;
	if (d >= gap)
		continue;

	// Склеить
	clist[0]=c;
	clist[1]=cc;
	compose_cell(2,clist,c);

	// Заменить версию
	switch(let)
		{
		case 'd': c->vers[0].let = d_inv_roof; break;
		case 't': c->vers[0].let = t_inv_roof; break;
		}

	if (db_status)
		snap_newcell(c);

	if (snap_activity('e'))
		{
		snap_show_text("czech_dt_glue_apostroph");
		snap_monitor();
		}
	}

}
//*******************************************************************
