/*
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.
*/

/* DIFFR.C : diskrimintion functions for russian language */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "tech.h"
#include "tuner.h"
/*
#ifdef __MAC__
#define __WATCOMC__
#endif				  */

/*#ifdef __WATCOMC__  */
#include "nt_types.h"
#include "ligas.h"

#include "status.h"	// 08.09.2000 E.P.
#include "lang_def.h"	// 08.09.2000 E.P.
#include "linutil.h"

#include "compat_defs.h"

BYTE broken_flag=0;
BYTE rec5_flag=1,font_type=0,omni=1;
/*#else					// А ЭТО Turbo C

	typedef signed char		CHAR;
	typedef	unsigned char		BYTE;
	typedef signed int		INT;
	typedef unsigned char *		PBYTE;
			// определения типов : для совместимости с WATCOM
			// INT	- int
			// CHAR - char
			// BYTE - unsigned char

	#define memset  memset

	#define abs  abs
	#define MAX  max
	#define MIN  min
	#define MEMCHR memchr

	extern INT rec5_flag;           // recognition by 5 points flag
	extern BYTE  font_type;
	extern BYTE  omni;              // recognition  by  omnifont
	extern INT broken_flag;

#endif	 */
static INT AngleBottomLeft(BYTE *raster,INT D_X,INT hei);
static INT AngleTopLeft(BYTE *raster,INT D_X,INT hei);
static INT AngleBottomRight(BYTE *raster,INT D_X,INT hei);
static INT AngleTopRight(BYTE *raster,INT D_X,INT hei);
INT AnglesCurve(BYTE *raster,INT D_X,INT hei);

#ifdef UFA
static INT Diskr5(BYTE *raster,INT D_X,INT hei);
static INT Diskr2(BYTE *raster,INT D_X,INT hei);
static INT OlegJurit( BYTE *R, INT D_X, INT dy);
static INT DiskrHoriz(BYTE *R,INT D_X,INT hei);
#include "Tab_angl.H"
#endif

INT  LinesWithNumIntervals(BYTE *rastr,INT D_X,INT dy,INT num);
INT  NumVertInterval(BYTE *RASTER,INT D_X, INT dy, INT i);
INT  VertSum(BYTE *rastr,INT D_X, INT dy, INT i);
INT  SumBits(BYTE *rastr,INT D_X);
INT  NumHorizInterval(BYTE *,INT);
INT  MinMaxRight(BYTE *raster,INT D_X,BYTE dx,
				BYTE Ly, INT *mi,INT *ma);
INT  MinMaxLeft (BYTE *raster,INT D_X,BYTE dx,
				BYTE Ly, INT *mi,INT *ma);
INT  FOOT(BYTE *raster,INT DX,BYTE dx,BYTE Ly,
		BYTE sign_filter);
INT  FOOT3(BYTE *raster,INT DX,BYTE start,BYTE dx,BYTE Ly, INT SHIFT);
INT  FOOT3_2(BYTE *raster,INT DX,BYTE dx,BYTE Ly);
INT  FOOT_A(BYTE *raster,INT DX,BYTE dx,BYTE Ly);
INT  Asymm_let(BYTE *raster,INT DX,BYTE dx,
		  BYTE Ly,BYTE TW);

INT  LeftDistance(BYTE *RASTER,INT dx);
INT  RightDistance(BYTE *RASTER,INT dx);
INT  SumIntervalBits(BYTE *RASTER,INT bx,INT ex);
INT  CenterVertInterval(BYTE *,INT ,INT ,INT, INT *,INT *);
INT  LeftEdgeOfRightmostInt( BYTE *rst, INT Wdth);
INT EndBlackInterval(BYTE *RASTER, INT NWIDTH);
static INT DiskrSymSh( BYTE *RASTER, INT Wx, BYTE NWIDTH, BYTE NLENGTH);
static INT Diskr9(BYTE *rastr,INT D_X,INT dy,INT dx);
static INT DiskrLeftBottomHole(BYTE *raster,INT D_X,INT hei,INT lim);
static INT DiskrRightTopHole(BYTE *raster,INT D_X,INT hei,INT lim);
static INT LepikJurit( BYTE *r,INT D_X, INT dy);
static INT Num2Interval(BYTE *r,INT D_X,INT dx,INT dy);
static INT broken_M(BYTE * r,INT D_X,INT dy,INT ll1, INT ll);
static INT descr_ce(BYTE *r,INT D_X,INT h);
#ifndef INTERSEPTOR
//static INT DiskrJu(BYTE *RASTR,INT D_X,INT dx,INT Ly);
#else
static INT DiskrJu1(BYTE *RASTR,INT D_X,INT dx,INT Ly);
#endif
static INT Diskr3(BYTE *RASTR,INT D_X,INT dx,INT Ly);
static INT DiskrJ0(BYTE *RASTR,INT D_X,INT dx,INT Ly,INT lim);
static int DiskrJ(unsigned char *RASTR,int D_X,int dx,int dy);
static INT DiskrSh(BYTE *RASTR,INT D_X,INT dx,INT Ly);
static INT DiskrLeft(BYTE *RASTR,INT D_X,INT dx,INT Ly, INT L);
static INT DiskrLeftBig(BYTE *RASTR,INT D_X,INT dx,INT Ly, INT L);
static INT DiskrRight(BYTE *RASTR,INT D_X,INT dx,INT Ly, INT L);
static INT DiskrRightBig(BYTE *RASTR,INT D_X,INT dx,INT Ly, INT L);
static INT DiskrVertCE(BYTE *RASTR,INT D_X,INT dx,INT dy,INT X,BYTE l,BYTE inc);
static INT DiskrSh0(BYTE *RASTR,INT D_X,INT dx,INT dy,INT dx0);
static INT DiskrTsh(BYTE *RASTR,INT D_X,INT dx,INT dy,INT Dx);
static void DiskrIN(BYTE *RASTR,INT D_X,INT dy, INT wb,INT dx);
static INT DiskrHorizIN(BYTE *RASTR,INT D_X,INT dy);
static INT DiskrEZ(BYTE *RASTR,INT D_X,INT dx,INT dy);
static INT DiskrimM(PBYTE RAST,INT D_X,INT dx,INT dy);
static INT DiskrimM1(BYTE *RAST,INT D_X,INT dx,INT dy);
static INT whiteMeanBitLeft(BYTE *RAST,INT D_X,INT meanBit);
static INT whiteMeanBitRight(BYTE *RAST,INT D_X,INT dx,INT meanBit);
static INT up_down_hist_M(BYTE *rastr,INT D_X, INT Dx,INT dy);
static INT average_angle(BYTE *RASTER, INT D_X, INT dx, INT dy,
			 INT  (*Distance)(BYTE *,INT),INT t);
static INT average_tl_angle(BYTE *RASTER, INT D_X, INT dx, INT dy,INT t);
static INT average_bl_angle(BYTE *RASTER, INT D_X, INT dx, INT dy,INT t);
static INT average_br_angle(BYTE *RASTER, INT D_X, INT dx, INT dy,INT t);
static INT NoSymmLastColumn(BYTE *raster,INT D_X,INT Dx,INT dy);
INT no_serific(BYTE *RASTR,INT dy,INT dx,INT wb);
static INT fill_center_zone(BYTE *raster,INT D_X,INT dy,
        INT beg, INT end, INT II);
static INT up_down_zones(BYTE *raster,INT D_X,INT dx,INT dx0,
			INT start1,INT stop1,
			INT start2,INT stop2);
static INT up_down_zones_for_B(BYTE *raster,INT D_X,INT dx,INT dx0,
			INT start1,INT stop1,
			INT start2,INT stop2);
static INT small_density(BYTE *RAST,INT n,INT D_X,INT bw);
static INT horiz_density(BYTE *RAST,INT D_X,INT dx,INT beg,INT end);
#ifdef INTERSEPTOR
static INT DiskrVV(BYTE *raster,INT D_X,INT hei);
static INT DiskrII(BYTE *raster,INT D_X,INT hei);
#endif

#define bytlen(bits)  ((bits+7)>>3)

extern BYTE BUFFER[256];        /* вертикальная   прoекция              */
extern BYTE LOCAL[50];        	/* координаты     ног          		*/
extern BYTE LOCAL_W[50];      	/* ширины         ног          		*/
extern BYTE end1,beg2;        	/* конец 1 и начало 2-ой ног инп	*/
extern broken_ii;		/* флаг двух палок			*/
extern INT dnri_hook; // bottom right hook in small russian italic II,III
extern INT uple_hook; // bottom left  hook in small russian italic II,III
extern INT up_jack  ; // upper jack

static INT upper_skip_lines,lower_skip_lines;
static INT diskr_g,diskr_sh,diskr_b,diskr_k,diskr_ju,diskr_f2,diskr_tsh,
	diskr_ii,IN_N_Bonus,IN_P_Bonus,IN_I_Bonus,IN_IN_Monus,diskr_N,
    diskr_o,diskr_c,diskr_e,diskr_h,diskr_ja,diskr_z,diskr_ee,diskr_d,
    diskr_ce,IN_dis,diskr_i,diskr_n,diskr_p,IN_equ,IN_N,IN_I,IN_M,IN_pics,
    diskr_m,mii,diskr_tsche,diskr_l,
    diskr_EZ,diskr_B,diskr_E,diskr_y,
    diskr_9,diskr_6,diskr_5,diskr_2,diskr_8;
INT left_dist[4], right_dist[4], num_foot, c_or_e,d_c,d_e,
    right_max,left_max,left_line,right_line,
    left_dist_big[4], right_dist_big[4],lower_long_line;
INT av_tl, av_bl,av_br, rotate;
/* g-Ж, sh-Ш, b-B, k-K, ju-Ю, f2-ИНП, tsh-Щ, ii-Ы, o-O, c-C, e-E,
   h-Х, ja-Я, z-З, ee-Э, d-Д, ce-Ц  */
INT fill_center,up_down_serif,up_down_serif_B,IN_horiz_dis,broken_M_pen;

/*  clear diskrimination flags */
void init_diskrim(PBYTE raster,INT height ,INT width)
{
INT i, D_X=bytlen(width);
PBYTE r;

rotate=0;
diskr_g=diskr_sh=diskr_b=diskr_k=diskr_ju=diskr_f2=
diskr_tsh=diskr_ii=diskr_o=diskr_c=diskr_e=diskr_ee=
diskr_9=diskr_5=diskr_6=diskr_2=diskr_8=diskr_N=
diskr_h=diskr_ja=diskr_z=diskr_d=diskr_ce=diskr_l=
left_dist_big[1]= right_dist_big[1]= left_dist[1]= right_dist[1]=
left_dist_big[2]= right_dist_big[2]= left_dist[2]= right_dist[2]=
left_dist_big[3]= right_dist_big[3]= left_dist[3]= right_dist[3]=
num_foot= c_or_e=d_c=d_e=diskr_EZ=
diskr_B=diskr_E=diskr_y=
fill_center=IN_dis=diskr_i=diskr_n=diskr_p=IN_equ=IN_N=IN_I=IN_M=
IN_pics=up_down_serif=up_down_serif_B=IN_horiz_dis=
diskr_m=diskr_tsche=broken_M_pen=
lower_long_line=right_max=left_max=-1;
av_tl=av_bl=av_br=-1;
mii=-101;

IN_N_Bonus=0;
IN_P_Bonus=0;
IN_I_Bonus=0;
IN_IN_Monus=0;

r = raster;
for(  i=0;i<height && SumBits( r ,D_X)<3;i++,r+=D_X);
upper_skip_lines = i;

r = raster + D_X*(height-1);
for(  i=0;i<2 && SumBits( r ,D_X)<3;i++,r-=D_X);
lower_skip_lines = i;

return;
}

/* Diskrim : diskrimination function for diapason 0-255    */
/* PARAMETRS :                                             */
/*	let    - name of letter                            */
/*	raster - bit map( work raster )                    */
/*	D_X    - whidth of bit map( length bit string )    */
/*	X,Y    - coordinats of first point in raster       */
/*	dx,dy  - whidth and height work raster             */
/*							   */
/*   RETURN :   0 - good letter                            */
/*	       >0 - decreasing code                        */

INT Diskrim(BYTE let,PBYTE raster,
      INT D_X,INT X,INT Y,INT dx,INT dy,BYTE cg_flag, INT inc)
{
INT P=0,F=0,Dx,Hy,n,bw;
BYTE *rastr,*rastr0;
INT d_l, d_r;
#define  step_diskr 20

rotate= (inc>180) ;
if( upper_skip_lines )
	{
	raster += bytlen(D_X)*upper_skip_lines;
	dy-=upper_skip_lines;
	}
if( lower_skip_lines &&
	! (memchr("цЦщЩ",let,4) &&
		!is_russian_turkish_conflict(let) // 21.05.2002 E.P.
	  )
   )
	{
	dy-=lower_skip_lines;
	}

if( dy<8 || dx<3 )
	return(step_diskr*10);

D_X = bytlen(D_X);
Dx = dx + (X&7);
bw = bytlen(Dx);
rastr0= raster + Y*D_X+(X>>3);
rastr = rastr0 + D_X*(dy>>2);
Hy = dy-2*(dy>>2);
d_l = (X&7)+(dx>>2);
d_r = ((bytlen(Dx))<<3)-dx-(X&7)+(dx>>2);

switch( (BYTE)let )
	{
  case (BYTE)'N' :
		if( diskr_N<0 )
		{
        BYTE rasterN[4096];
        int i,ii,iii;

        for(iii=D_X*(dy-1),ii=i=0;i<dy;i++,ii+=D_X,iii-=D_X)
            memcpy(rasterN+iii,raster+ii,D_X);
        rastr0= rasterN + Y*D_X+(X>>3);
        rastr = rastr0 + D_X*(dy>>2);
        F = FOOT(rastr, D_X,(BYTE)Dx, (BYTE)Hy,1);
		if( F!=2 || MIN(LOCAL_W[0],LOCAL_W[1])>3 && beg2-end1<3 )
			{
			if( dy>13 )
				F=FOOT(rastr0+2*D_X, D_X,(BYTE)Dx, (BYTE)(dy-4),0);
			else
				F=FOOT(rastr0, D_X,(BYTE)Dx, (BYTE)dy,0);
			}
		if( F!=2 )
			{
			if( small_density(rastr,Hy,D_X,bw) )
				P = 6*step_diskr;
			else
				P += step_diskr;
                        if( F==3 )
				P +=6*step_diskr;
			}
		   else
		   {
           IN_dis=-1;
		   DiskrIN(rastr0,D_X,dy,bw,dx);
		   IN_dis=-1;
           if( 2*LOCAL[0]>5*LOCAL_W[0] && 2*(dx-LOCAL[1])<3*LOCAL_W[1])
            P += 2*step_diskr;
		   if( IN_I<3 )
			P += MIN(2*(7-IN_I+IN_equ) * step_diskr,160)/2;
		   else if( IN_I==3 && IN_equ>2 )
			P += IN_equ*step_diskr;
		   //if( IN_I>10 && IN_M==0 )
            //P += 40;
		   }

      if( inc>0 )  // OLEG : ERECTION conditions : 09-12-95 07:29pm
        P >>= 1;

		diskr_N = P;
		}
		else P=diskr_N;
        IN_dis=-1;
        IN_IN_Monus=0;
        IN_pics=1;
        IN_M=0;
		break;

  case (BYTE)'М' :  case (BYTE)'м' :
                if( omni )
                {
                if( diskr_m<0 )
			{
			if( mii<-100 ){
			   if(broken_flag)
			      mii = DiskrimM1(rastr0, D_X, dx, dy );
			   else
			      mii = DiskrimM(rastr0, D_X, dx, dy );
			}
		if(mii>0)
			P+= mii*step_diskr;
		if(mii==0)
			       P+= 5*step_diskr;

		if( dy>13 )
			F=FOOT(rastr0+2*D_X, D_X,(BYTE)Dx, (BYTE)(dy-4),0);
		else
			F=FOOT(rastr0, D_X,(BYTE)Dx, (BYTE)dy,0);

                   if( F==2 )
			{
			DiskrIN(rastr0,D_X,dy,bw,dx);
			if( LOCAL[0] > dx/4)
				P >>=2 ;
			P += IN_M;
			}

                        diskr_m = P;
			}
		else  P = diskr_m;
		}
		break;
  case (BYTE)'Ы' :  case (BYTE)'ы' :
		if( diskr_ii<0 )
      {
			if( omni )
			 {
			 if( mii<-100 )
			    if(broken_flag)
			       mii = DiskrimM1(rastr0, D_X, dx, dy );
			    else
			       mii = DiskrimM(rastr0, D_X, dx, dy );
			    if(mii<0)
				 P += (-mii)*step_diskr;
			    if(mii==0)
				 P+= 5*step_diskr;
			 }
			diskr_ii = P;
			}
		else  P = diskr_ii;
		break;

  case (BYTE)'Б' :
	if(omni){
		if( diskr_B<0 )
		   {
		   if( !DiskrRight(rastr0, D_X, Dx, dy,2) )
			P = step_diskr;
		   diskr_B = P;
		   }
		   else P = diskr_B;
		}
		break;
  case (BYTE)'Е' :
	if(omni){
		if( diskr_E<0 )
		   {
		   if( !horiz_density(rastr0,D_X,dx,Hy,dy) )
			P = step_diskr;
		   diskr_E = P;
		   }
		   else P = diskr_E;
		}
		break;
  case (BYTE)'Д' :  case (BYTE)'д' :
		if( diskr_d<0 )
		   {
		   if( average_bl_angle(rastr0,D_X,Dx,dy,0)>d_l )
			P = 4*step_diskr;
		   if( average_br_angle(rastr0,D_X,Dx,dy,0)>d_r )
                        P += 2*step_diskr;
		   if( !horiz_density(rastr0,D_X,dx,Hy,dy) )
			P += step_diskr;
		   diskr_d = P;
		   }
		   else P = diskr_d;
		break;
  case (BYTE)'К' :  case (BYTE)'к' :
		if( diskr_k<0 )
		   {
                   if( font_type==0  )
		   {              	/* Poly 	*/
		   if( !DiskrRightBig(rastr0, D_X, Dx, dy,2) )
			P=3*step_diskr;
                   // OLEG : ERECTION EFFECT : 09-22-95 07:32pm
                   if( !(rotate && dnri_hook) )
                        {
                        if( DiskrLeft(rastr0, D_X, Dx, dy,2) )
                                P+=3*step_diskr;
                        if( DiskrJ0(rastr, D_X, Dx, Hy,(INT)(dy<18?4:5))==0 )
                                P+=5*step_diskr;
                        }
                   else
                      {
                      if( DiskrLeft(rastr0, D_X, Dx, dy,2) )
                        P+=3*step_diskr;
                      }
		   }
		   else
		   {			/* Twrite	*/
		   if( !DiskrRight(rastr0, D_X, Dx, dy,2) )
			P=3*step_diskr;
		   }
		   diskr_k = P;
		   }
		   else P = diskr_k;
		break;
  case (BYTE)'В' : /*     case 'в' :*/
#ifdef INTERSEPTOR
  case (BYTE)'в' :
#endif
		if( diskr_b<0 )
		   {
#ifdef INTERSEPTOR
       if( DiskrVV(rastr0,D_X,dy)==2 )
        P += 100;
#endif
		   if( !DiskrRight(rastr0, D_X, Dx, dy,1) )
        {    /* нет дырки */
        if( dy<=19 ) /* маленькие 'в' не имеют дырочки */
          {
          if( !omni )
          if( !NoSymmLastColumn(rastr0,D_X,Dx,dy) )
            P+=3*step_diskr;
          }
        else        /* большие должны иметь вмятину */
          {
#ifdef INTERSEPTOR
          if( dy>22 )
          if( !NoSymmLastColumn(rastr0,D_X,Dx,dy) )
#endif
            P+=2*step_diskr;
          }
        }
		   else
        {   /* вмятина есть */
        if( (n=up_down_zones_for_B(rastr0,D_X,Dx,dx,0,(INT)(dy>>2),Hy,dy))==1 )
          {
          if( !omni )
            P+=n*2*step_diskr;
          else if( n==2 )
            P+=step_diskr;
          }
       }

		   diskr_b = P;
		   }
		   else P = diskr_b;
		break;
	case '3' :
  case (BYTE)'З' :  case (BYTE)'з' :
   if( diskr_z<0 )
     {
		   if( !DiskrRight(rastr0, D_X, Dx, dy,1) )
		   {    /* нет дырки */
	 if(dy<14 && DiskrEZ(rastr0, D_X, dx, dy)==1 )
                      P+=step_diskr;
	 else
	    if( (dy<21) ||(cg_flag&16)) /* маленькие 'з' не имеют дырочки */
               {
                if( dy>13 &&(!(cg_flag&16)))
		  if(!NoSymmLastColumn(rastr0,D_X,Dx,dy) )
				P+=3*step_diskr;
	       }
	    else        /* большие должны иметь вмятину */
		P+=2*step_diskr;
       }
#ifdef UFA
    else if( right_max>0 && right_max>=(dx*5)/12 )   // (1/2 + 1/3 ) /2
      P += step_diskr;
		if(  OlegJurit(rastr0,D_X,dy) )
			P += 3*step_diskr;
#endif
		   diskr_z = P;
		   }
		   else P = diskr_z;
		break;

  case (BYTE)'Э' :  case (BYTE)'э' :

	   // ┬ сюыурЁёъюь эхЄ ▌¤. 08.09.2000 E.P.
	   if (language==LANG_RUSSIAN && langBul)
			{P=200;break;}

		if( diskr_ee<0 )
		   {
       if( DiskrRight(rastr0, D_X, (INT)((dy<20)?Dx:Dx-1), dy,1) )
			P+=2*step_diskr;

       if( dy>13 && dy<21)
		 if(cg_flag&16) /* cut at right side*/
		   {
		   if (LepikJurit(rastr0,D_X,dy))
			   P+=3*step_diskr+2;
		   }
                 else
		   {
		   if (NoSymmLastColumn(rastr0,D_X,Dx,dy) )
			     P+=2*step_diskr;
                   }
		   if(dy<14 && DiskrEZ(rastr0, D_X, dx, dy)==2 )
			   P+=step_diskr;
		   diskr_ee = P;
		   }
		   else P = diskr_ee;

		break;
       /* case (BYTE)'Я' : */     case (BYTE)'я' : /*Valdemar 9.03.94*/
		if( diskr_ja<0 )
		   {
		   if( !DiskrLeft(rastr0, D_X, Dx, dy,1) ) P=2*step_diskr;
                   if( !omni )
                   { /* для omni есть дискриминаторы углов */
		   if( average_bl_angle(rastr0,D_X,Dx,dy,1) >=
		       average_tl_angle(rastr0,D_X,Dx,dy,1)  )
			P+=2*step_diskr;
		   }
		   diskr_ja = P;
		   }
		   else P = diskr_ja;
		break;
/*  case '8' :*/
  case (BYTE)'Х' :
	   if (is_turkish_language(language)) // 21.05.2002 E.P.
		  break;
  case (BYTE)'х' :
		if( diskr_h<0 )
		   {
		   if( !DiskrLeftBig(rastr0, D_X, Dx, dy,1) )
			P+=3*step_diskr;
		   if( !DiskrRightBig(rastr0, D_X, Dx, dy,1) )
			P+=3*step_diskr;

                   if( (n=Diskr3(rastr0+D_X*(dy>>1), D_X, Dx, Hy))!=0 && // down
                        (F=Diskr3(rastr0, D_X, Dx, Hy))!=0 )        // up
                        P +=3*step_diskr; // similar >|<
                   diskr_h = P;
		   }
		   else P = diskr_h;
		break;
  case (BYTE)'Ж' :  case (BYTE)'ж' :
		if( diskr_g<0 )
		   {
		   if( !DiskrLeftBig(rastr0, D_X, (BYTE)Dx, (BYTE)dy,2) )
        P+=3*step_diskr;
		   if( !DiskrRightBig(rastr0, D_X, Dx, dy,2) )
        P+=3*step_diskr;
       F = FOOT(rastr, D_X,(BYTE)Dx, (BYTE)Hy,0);
       if( F!=3 && (n=DiskrJ0(rastr, D_X, Dx, Hy,(INT)(dy<18?4:5)))!=0 )
        { /* в средней половине нет 3-частных линий */
        if( !DiskrJ(rastr0, D_X, Dx, dy) )
          P+=2*n*step_diskr;
        }
       if( F!=3 && (n=DiskrJ0(rastr0, D_X, Dx, Hy,(INT)(dy<18?2:3)))!=0 )
        { /* в верхней половине нет 3-частных линий */
        if( !DiskrJ(rastr0, D_X, Dx, dy) )
          P+=2*n*step_diskr;
        }
#ifdef INTERSEPTOR
      if( let==(BYTE)'ж' && dx>55 )
        P += 160;
#endif
       diskr_g = P;
		   }
		   else P = diskr_g;
		break;
  case (BYTE)'Ю' :
  case (BYTE)'ю' :
	   if (is_turkish_language(language)) // 21.05.2002 E.P.
		  break;
	   if( diskr_ju<0 )
		   {
#ifdef INTERSEPTOR
         if( (F=DiskrJu1(rastr0, D_X, Dx, dy))!=0)
#endif
       if( DiskrLeft(rastr0, D_X, Dx, dy,2) )
      P += 2*step_diskr;
		   if( DiskrRight(rastr0, D_X, Dx, dy,2) )
      P += 2*step_diskr;
#ifdef INTERSEPTOR
      if( let==(BYTE)'ю' && dx>55 )
        P += 160;
#endif
		   diskr_ju = P;
		   }
		   else P = diskr_ju;
		break;
  case (BYTE)'Ц' :  case (BYTE)'ц' :
		if( diskr_ce<0 )
			{
      if( (F=FOOT(rastr0+2*D_X, D_X,(BYTE)Dx, (BYTE)Hy,0))!=2 )
				P = 4*step_diskr;
			if( average_br_angle(rastr0,D_X,Dx,dy,0)>d_r+1 )
				P += 4*step_diskr;
      if( !(uple_hook && rotate) )
      if( F==2 && descr_ce(rastr0+(dy-3)*D_X,D_X,(INT)(dy/2)) )
				P += 6*step_diskr;
			diskr_ce = P;
			}
		else  P = diskr_ce;
		break;
  case (BYTE)'Ш' :  case (BYTE)'ш' :
		if( diskr_sh<0 )
		   {
       FOOT(rastr, D_X,(BYTE)Dx, (BYTE)Hy,0);
       if( rotate ) // OLEG : ERECTION conditions : 09-20-95
        {
        F=FOOT3(rastr, D_X, (BYTE)(uple_hook?LOCAL[0]-LOCAL_W[0]/2:0 ),
                            (BYTE)(dnri_hook?LOCAL[2]+LOCAL_W[2]/2:Dx), (BYTE)Hy,(BYTE)(Hy<10?1:2));
        if( F!=3 )
          P  = 10*step_diskr;
        }
      else
        {
        if( (F=FOOT3(rastr, D_X, 0, (BYTE)Dx, (BYTE)Hy,2))!=3 )
          P  = 10*step_diskr;
        else
          P += (step_diskr>>1)*DiskrSymSh(rastr, D_X, (BYTE)Dx, (BYTE)Hy);
        }
       if( inc<=0 && !broken_flag && DiskrSh0(rastr0, D_X, Dx, dy, dx)==0 )
        P +=/*4**/step_diskr;
		   F = FOOT(rastr, D_X,(BYTE)Dx, (BYTE)Hy,0);
       // OLEG : ERECTION conditions : 09-20-95 08:34pm
			 if( inc>0 && dnri_hook )
        {
        if( DiskrSh(rastr, D_X, (INT)(LOCAL[2]+LOCAL_W[2]/2), Hy) )
          P += step_diskr;
        }
       else
        {
        if( (n=DiskrSh(rastr, D_X, Dx, Hy))!=0 )
          P += n*step_diskr;
        }
		   if( F!=3  )
        P += 12*step_diskr;
		   if( DiskrLeft(rastr0, D_X, Dx, dy,2) )
        P += step_diskr/2;
		   if( DiskrRight(rastr0, D_X, Dx, dy,2) )
        P += step_diskr/2;
       if( FOOT3_2(rastr0,D_X,(BYTE)Dx,(BYTE)dy) )
        P += step_diskr*3;
		   diskr_sh = P;
       P=MAX(P,0);
       }
		   else  P = diskr_sh;
		break;

  case (BYTE)'П' :  case (BYTE)'п' :
		if( diskr_p )
			{
      if( dy>13 )
        F=FOOT(rastr0+2*D_X, D_X,(BYTE)Dx, (BYTE)(dy-4),0);
      else
        F=FOOT(rastr0, D_X,(BYTE)Dx, (BYTE)dy,0);
#ifdef UFA
    if( F==1 && broken_flag )
      F = FOOT(rastr, D_X,Dx, Hy,1);
#endif
			if( F!=2 )
				P = 6*step_diskr;
			else
        { // F==2
        if( rotate && (dnri_hook||dy<22&&up_jack>1) )
          fill_center_zone(rastr+D_X*(Hy>>2),D_X,(INT)(Hy-(Hy>>2)),end1,beg2,1);
        else
          fill_center_zone(rastr,D_X,Hy,end1,beg2,0);
        {
        INT f_c=fill_center;
        DiskrIN(rastr0,D_X,dy,bw,dx);
        if( !(rotate && (dnri_hook||dy<22&&up_jack>1)) )
          f_c = fill_center;
        if( f_c==1 )
          P += 8*step_diskr;
        }
      }

			if( (n=up_down_zones(rastr0,D_X,Dx,dx,0,(INT)(dy>>2),Hy,dy))!=0 )
				{
				if( omni )
				{
				if( n!=1 )
					P += 4*step_diskr*n;
				}
				else
				{	/* no omni	*/
				if( !broken_flag || n==2 )
					P += 4*step_diskr*n;
				else
					P += 1*step_diskr;
				}
				}

			if( 	IN_P_Bonus && broken_flag && (broken_ii ||
				!IN_IN_Monus &&
				Num2Interval(rastr0+2*D_X, D_X,Dx, (INT)(dy-4))) )
					P =(IN_P_Bonus==2)?-254:-250;

      diskr_p = P;
			}
		else P = diskr_p;
		break;
  case (BYTE)'И' :  case (BYTE)'и' :
		if( diskr_i<0 )
		{
		F = FOOT(rastr, D_X,(BYTE)Dx, (BYTE)Hy,1);
		if( F!=2 || MIN(LOCAL_W[0],LOCAL_W[1])>3 && beg2-end1<3 )
			{
			if( dy>13 )
				F=FOOT(rastr0+2*D_X, D_X,(BYTE)Dx, (BYTE)(dy-4),0);
			else
				F=FOOT(rastr0, D_X,(BYTE)Dx, (BYTE)dy,0);
			}
		if( F!=2 )
			{
			if( small_density(rastr,Hy,D_X,bw) )
				P = 6*step_diskr;
			else
				P += step_diskr;
                        if( F==3 )
				P +=6*step_diskr;
			}
		   else
		   {
       if( rotate && dnri_hook )
        fill_center_zone(rastr+D_X*(Hy>>2),D_X,(INT)(Hy-(Hy>>2)),end1,beg2,0);
      else
        fill_center_zone(rastr,D_X,Hy,end1,beg2,0);
		   DiskrIN(rastr0,D_X,dy,bw,dx);
		   if( fill_center==0 )
			{
			if( broken_flag )
				{
				if( IN_I<=3 || IN_pics==0 )
					P += 2*step_diskr;
				}
			else
				P += 8*step_diskr;
			}
		   if( IN_I<3 )
			P += MIN(2*(7-IN_I+IN_equ) * step_diskr,160)/2;
		   else if( IN_I==3 && IN_equ>2 )
			P += IN_equ*step_diskr;
      if( IN_I>=9 )
        { /* очень негоризонтальная перекладина */
        if( (F=up_down_hist_M(rastr0+D_X, D_X,Dx, (INT)(dy-2)))>0 )
          P += F*step_diskr>>2;
        if( LOCAL[1]>(Dx>>1) &&
        broken_M(rastr0+2*D_X, D_X,(INT)(dy-4),(INT)(LOCAL[0]-LOCAL_W[0]/2),
          (INT)(LOCAL[1]-LOCAL_W[1]/2)) )
          P += 4*step_diskr;
        }
		   }
      if( inc>0 )  // OLEG : ERECTION conditions : 09-12-95 07:29pm
        P >>= 1;
      if(     IN_I_Bonus && broken_flag && (broken_ii ||
			!IN_IN_Monus &&
			Num2Interval(rastr0+2*D_X, D_X,Dx, (INT)(dy-4))) )
			P =(IN_I_Bonus==2)?-254:-250;
		diskr_i = P;
		}
		else P=diskr_i;
		break;
  case (BYTE)'Н' :  case (BYTE)'н' :
		if( diskr_n<0 )
		{
		F = FOOT(rastr, D_X,(BYTE)Dx, (BYTE)Hy,1);
		if( F!=2 || MIN(LOCAL_W[0],LOCAL_W[1])>3 && beg2-end1<3 )
			{
			if( dy>13 )
				F=FOOT(rastr0+2*D_X, D_X,(BYTE)Dx, (BYTE)(dy-4),0);
			else
				F=FOOT(rastr0, D_X,(BYTE)Dx, (BYTE)dy,0);
			}
		if( F!=2 )
			P = 6*step_diskr;
		else
		   {
      if( rotate && dnri_hook )
        fill_center_zone(rastr+D_X*(Hy>>2),D_X,(INT)(Hy-(Hy>>2)),end1,beg2,0);
      else
        fill_center_zone(rastr,D_X,Hy,end1,beg2,0);
		   DiskrIN(rastr0,D_X,dy,bw,dx);
		   if( DiskrHorizIN(rastr0,D_X,dy) )
			{   /* жирная перекладина */
			IN_N=3;
			IN_I=2;
			}
		   if( fill_center==0 )
			{
			if( broken_flag )
				{
				if( IN_N>=3 || IN_pics==0 )
					P += 2*step_diskr;
				}
			else
				P += 8*step_diskr;
			}

		   if( IN_N>3 )
			P += MIN(IN_N * step_diskr,160)/2;
		   if( DiskrRight(rastr0, D_X, Dx, dy,(INT)(dy>22?3:2)) )
			P += 3*step_diskr;
		   if( omni )
			{
			if( LOCAL_W[0]>(LOCAL_W[1]<<1) &&
			(LOCAL_W[1]>1 || LOCAL_W[1]==1 && LOCAL_W[0]>3 ) )
				P += 2*step_diskr;
			}
		   }
    if( IN_N_Bonus && broken_flag && (broken_ii ||
			!IN_IN_Monus &&
			Num2Interval(rastr0+2*D_X, D_X,Dx, (INT)(dy-4))) )
			P =(IN_N_Bonus==2)?-254:-250;
		diskr_n = P;
		}
		else P=diskr_n;
		break;


  case '<' :
    if( !DiskrRightBig(rastr0, D_X, Dx, dy, 1) )
			P = 3*step_diskr;
                /*
                DiskrLeft(rastr0, D_X, Dx, dy, 2);
		if( left_line==1 )
			P+=3*step_diskr;
                 */
		break;
	case '>' :
    if( !DiskrLeftBig(rastr0, D_X, Dx, dy, 1) )
			P = 3*step_diskr;
      /*
                DiskrRight(rastr0, D_X, Dx, dy, 2);
		if( right_line==1 )
			P+=3*step_diskr;
       */
		break;
	case '0' :
  case (BYTE)'О' :
  case (BYTE)'о' :
	    if (is_turkish_language(language)) // 21.05.2002 E.P.
		  break;

		if( diskr_o<0 )
		   {
		   if( DiskrRight(rastr0, D_X, Dx, dy, 2) )
				P = step_diskr;
		   diskr_o = P;
		   }
		   else  P = diskr_o;
		break;
  case (BYTE)'С' :  case (BYTE)'с' :
		if( diskr_c<0 )
		   {
		   if( !DiskrRight(rastr0, D_X, Dx, dy, 2) )
				P = step_diskr;
                   if( (n=DiskrVertCE(rastr0, D_X, dx, dy, X,(BYTE)'с',(BYTE)inc))!=0 )
				P+=n*step_diskr;
		   diskr_c = P;
		   }
		   else  P = diskr_c;
		break;
  case (BYTE)'е' :
  case (BYTE)UKR_e : case (BYTE)UKR_E :
		if( diskr_e<0 )
		   {
                   if( (n=DiskrVertCE(rastr0, D_X, dx, dy, X,(BYTE)'е',(BYTE)inc))>2  )
				P+=(n-2)*step_diskr;
		   diskr_e = P;
		   }
		   else  P = diskr_e;
		break;
  case (BYTE)'ч' :
	    if (is_turkish_language(language)) // 21.05.2002 E.P.
		  break;
  case (BYTE)'Ч' : case '4' :
		if( diskr_tsche<0 )
		   {
		   if( dy>16 )
			n=FOOT(rastr0+2*D_X, D_X,(BYTE)Dx,(BYTE)(dy-4),2);
		   else
			n=FOOT(rastr0+D_X, D_X,(BYTE)Dx,(BYTE)(dy-2),2);

      if( n>1 || let!='4' && n==0 )
        P = 5*step_diskr;
      if( n>0 && LOCAL[0]<(Dx>>1) )
        P += 5*step_diskr;
      /*
      if( n==1 && LOCAL[0]>(Dx>>1) &&
        broken_M(rastr0+2*D_X, D_X,dy-4,LOCAL[0]-LOCAL_W[0]/2,
				LOCAL[0]-LOCAL_W[0]/2) )
        P += 4*step_diskr;
      */
      diskr_tsche = P;
		}
		else  P = diskr_tsche;
		break;
  case (BYTE)'Щ' :
	    if (is_turkish_language(language)) // 21.05.2002 E.P.
		  break;
  case (BYTE)'щ' :
		if( diskr_tsh<0 )
		   {
       F= ((BYTE)let==(BYTE)'Щ' )?4:2;
		   if( (F=FOOT(rastr0+F*D_X, D_X,(BYTE)Dx,(BYTE)Hy,0))!=3 )
        P = 10*step_diskr;
       else
        {
        P += (step_diskr>>1)*DiskrSymSh(rastr, D_X, (BYTE)Dx, (BYTE)Hy);
        if( DiskrTsh(rastr0+D_X,D_X,dx,dy,Dx)==1 )
          P += 3*step_diskr ;
        }
      if( average_br_angle(rastr0,D_X,Dx,dy,0)>d_r )
        P += 4*step_diskr;
      P=MAX(P,0);
      diskr_tsh = P;
      }
    else  P = diskr_tsh;
		break;
  #ifdef UFA
	case (BYTE)'б':
  #endif
	case '6' :
		if( diskr_6<0 )
		{
		if( DiskrLeft(rastr0, D_X, (INT)((dy<20)?Dx:Dx-1), dy,2) )
			P = step_diskr;
		if( DiskrLeftBottomHole(rastr,D_X,(INT)(dy/2),(INT)(dx>>1)) )
			P += 2*step_diskr;
		diskr_6 = P;
		}
		else P = diskr_6;
		break;
	case '9' :
		if( diskr_9<0 )
		{
		if( DiskrRight(rastr0, D_X, (INT)((dy<20)?Dx:Dx-1), dy,2) )
			P = 2*step_diskr;

#ifdef UFA
		if( P && AnglesCurve(rastr0,D_X,dy)>2 &&
			DiskrLeftBottomHole(rastr,D_X,dy/2,dx>>1) )
				P = 0;
#endif
		if( Diskr9(rastr,D_X,(INT)(dy/2),dx)     )
				P += 2*step_diskr;
		diskr_9 = P;
		}
		else P = diskr_9;
		break;
	case '8' :
		if( diskr_8<0 )
		   {
		   if( !DiskrLeft(rastr0, D_X, Dx, dy,1) )
			P+=2*step_diskr;
		   if( !DiskrRight(rastr0, D_X, Dx, dy,1) )
			P+=2*step_diskr;
		   if( !P && DiskrLeftBottomHole(rastr,D_X,(INT)(dy/2),(INT)(dx>>1)) )
			P += 2*step_diskr;
		   if( !P && DiskrRightTopHole(rastr,D_X,(INT)(dy/2),(INT)(dx>>1)) )
			P += 2*step_diskr;
		   diskr_8 = P;
		   }
		   else P = diskr_8;
		break;
    case '5' :
		if( diskr_5<0 )
    {
    if( !DiskrLeftBottomHole(rastr,D_X,(INT)(dy/2),(INT)(dx/2-((dy<21&&dx<15)?2:0))) )
      P += 2*step_diskr;
    diskr_5 = P;
		}
		else P = diskr_5;
    break;
#ifdef UFA
	case '5' :
		if( diskr_5<0 )
		{
		if( (F=Diskr5(rastr0,D_X,dy))!=0 )
			P = F*2*step_diskr;
		diskr_5 = P;
		}
		else P = diskr_5;
		break;
	case '2' :
		if( diskr_2<0 )
		{
		if( (F=Diskr2(rastr0,D_X,dy))!=0 )
			P = F*2*step_diskr;
		if( DiskrLeftBottomHole(rastr,D_X,dy/2,dx>>1) )
			P += 2*step_diskr;
		diskr_2 = P;
		}
		else P = diskr_2;
		break;
	case (BYTE)'Г' :
		if( 	DiskrHoriz(rastr,D_X,dy/2) &&
			(F=FOOT(rastr0+2*D_X, D_X,Dx, Hy,0))!=1 )
				P = 4*step_diskr;
		break;
#endif
	default  : break;
	}

#ifdef UFA
if( 	MaxCurveAngles[(BYTE)let] &&
	AnglesCurve(rastr0,D_X,dy)>MaxCurveAngles[(BYTE)let] )
		P += 3*step_diskr;
#endif
return(P & 0xFFFE);
}

INT Diskr9(BYTE *rastr,INT D_X,INT dy,INT dx)
{
INT l,r,i,d=dx>>1,num,black;
BYTE *rr;
for(rr=rastr,num=i=0;i<dy;i++, rr+=D_X)
	{
	l = LeftDistance(rr,D_X);
	r = RightDistance(rr,D_X)-8+(dx&7);
	black = SumBits(rr,D_X);
	if( black>d )
		num += ( dx-l-r-black<d);
	}

return !num;
}

INT DiskrLeftBottomHole(BYTE *raster,INT D_X,INT hei,INT lim)
{
INT i,pen;
BYTE *r;

for(pen=0,r=raster,i=0;i<hei;i++,r+=D_X)
	if( i>hei/4 && LeftDistance(r,D_X)>lim )
		pen++;
return pen>hei/4;
}

INT DiskrRightTopHole(BYTE *raster,INT D_X,INT hei,INT lim)
{
INT i,pen;
BYTE *r;

for(pen=0,r=raster,i=0;i<hei;i++,r+=D_X)
	if( i<hei/4 && RightDistance(r,D_X)>lim )
		pen++;

return pen>MIN(4,hei/4);
}

#ifdef UFA

INT DiskrHoriz(BYTE *R,INT D_X,INT hei)
{
INT i;
BYTE *rast=R;

for(i=0;i<hei;i++,rast+=D_X)
	if( NumHorizInterval(rast,D_X)==0 )
		return 0;
return 1;
}
INT OlegJurit( BYTE *R, INT D_X, INT dy)
{
  INT y2,y4,i,ld,rd, ret;
  BYTE *r;

  y2 = dy/2;
  y4 = dy/4;
  for (ld= D_X<<3,rd = i = 0, r = R+D_X*y4; i <y2;  i++ ,r+=D_X )
      {
	ret = LeftEdgeOfRightmostInt (r, D_X);
	if (rd<ret)rd=ret;
	if (ld>ret)ld=ret;
      }
 return rd-ld<3 && dy>24 || rd-ld<5 && dy>30 ;
}


INT Diskr5(BYTE *raster,INT D_X,INT hei)
{
int pen=0,inc;

inc = AngleTopRight(raster,D_X,hei);
if( inc>3 || hei<23 && inc>2 ) pen++;

inc = AngleTopLeft(raster,D_X,hei);
if( inc>3 || hei<23 && inc>2 ) pen++;

return pen;
}

INT Diskr2(BYTE *raster,INT D_X,INT hei)
{
int inc = AngleBottomLeft(raster,D_X,hei),pen=0;
if( inc>3 || hei<23 && inc>2 ) pen++;
return pen;
}


#endif

#ifdef INTERSEPTOR
INT DiskrVV(BYTE *raster,INT D_X,INT hei)
{
int inc = AngleBottomLeft(raster,D_X,hei),pen=0;
if( inc>5 ) pen++;
inc = AngleTopLeft(raster,D_X,hei);
if( inc>5 ) pen++;

return pen;
}

INT DiskrII(BYTE *raster,INT D_X,INT hei)
{
int pen=0,inc;

inc = AngleTopRight(raster-2*D_X,D_X,hei);
if( inc>4 ) pen++;

inc = AngleTopLeft(raster-2*D_X,D_X,hei);
if( inc>4 ) pen++;

inc = AngleBottomRight(raster+2*D_X,D_X,hei);
if( inc>4 ) pen++;

inc = AngleBottomLeft(raster+2*D_X,D_X,hei);
if( inc>4 ) pen++;

return pen;
}

#endif

INT AngleBottomRight(BYTE *raster,INT D_X,INT hei)
{
int i,old,neue,inc;
BYTE *r;

raster += D_X * (hei-2);
hei >>= 2;

old=RightDistance(raster,D_X);
for(inc=0,r=raster-D_X,i=1;i<hei;i++,r-=D_X)
	{
	neue = RightDistance(r,D_X);
	if( neue<old )		inc++;
	if( neue>old )		break;
	old  = neue;
	}
return inc;
}

INT AngleTopRight(BYTE *raster,INT D_X,INT hei)
{
int i,old,neue,inc;
BYTE *r;

raster += D_X;
hei >>= 2;

old=RightDistance(raster,D_X);
for(inc=0,r=raster+D_X,i=1;i<hei;i++,r+=D_X)
	{
	neue = RightDistance(r,D_X);
	if( neue<old )		inc++;
	if( neue>old )		break;
	old  = neue;
	}
return inc;
}

INT AngleBottomLeft(BYTE *raster,INT D_X,INT hei)
{
int i,old,neue,inc;
BYTE *r;

raster += D_X * (hei-2);
hei >>= 2;

old=LeftDistance(raster,D_X);
for(inc=0,r=raster-D_X,i=1;i<hei;i++,r-=D_X)
	{
	neue = LeftDistance(r,D_X);
	if( neue<old )		inc++;
	if( neue>old )		break;
	old  = neue;
	}
return inc;
}

INT AngleTopLeft(BYTE *raster,INT D_X,INT hei)
{
int i,old,neue,inc;
BYTE *r;

raster += D_X;
hei >>= 2;

old=LeftDistance(raster,D_X);
for(inc=0,r=raster+D_X,i=1;i<hei;i++,r+=D_X)
	{
	neue = LeftDistance(r,D_X);
	if( neue<old )		inc++;
	if( neue>old )		break;
	old  = neue;
	}
return inc;
}

INT AnglesCurve(BYTE *raster,INT D_X,INT hei)
{
int pen=0,inc;

inc = AngleBottomRight(raster,D_X,hei);
if( inc>3 || hei<23 && inc>2 ) pen++;

inc = AngleBottomLeft(raster,D_X,hei);
if( inc>3 || hei<23 && inc>2 ) pen++;

inc = AngleTopRight(raster,D_X,hei);
if( inc>3 || hei<23 && inc>2 ) pen++;

inc = AngleTopLeft(raster,D_X,hei);
if( inc>3 || hei<23 && inc>2 ) pen++;

return pen;
}

INT Num2Interval(BYTE *r,INT D_X,INT dx,INT dy)
{
INT i,n2,p,d;
d = bytlen(dx);
for(i=1;i<3;i++)
if( 	(p=NumHorizInterval(r-D_X*i,d))==1 &&
	(n2=SumBits(r-D_X*i,d))>dx-2 )
	return(0);
for(n2=i=0;i<dy; i++, r+=D_X )
	{
	p=NumHorizInterval(r,d);
	/*  NumHorizInterval : число интервалов в строке */
	n2 += (p==2 );
	}
return ( n2==dy );
}

/* broken_M : сходство с обломком М без левого копытца */
INT broken_M(BYTE * r,INT D_X,INT dy,INT left_lim,INT ll)
{
INT i,old,neue,dest,sign,fc,maxd,incr;
BYTE *rr;
if( broken_M_pen>=0 )
	return broken_M_pen;
old=RightDistance(r,D_X);
for(rr=r+D_X,i=1;i<dy;i++,rr+=D_X)
	{
	neue=RightDistance(rr,D_X);
	if( abs(neue-old)>1 )
		return (broken_M_pen=0);/* непрямой правый абрис */
	old=neue;
	}
/* прямой правый абрис */
old=LeftDistance(r,D_X);
dest=old;

for(maxd=fc=sign=incr=0,dest=old,rr=r+D_X,i=1;i<dy;i++,rr+=D_X)
	{
	neue=LeftDistance(rr,D_X);
	if( neue<old )
		{
		if( neue==old-1 )
			{
			if( sign )	return (broken_M_pen=0);
			else		sign=1;
			}
		else
		return(broken_M_pen=0);/* немонотонность левого абриса */
		}
	if( neue>=ll )	fc++;
	if( maxd<neue )
		maxd=neue;
  if( neue>=old  ) incr++;
	old=neue;
	}
dest = neue - dest;		/* скачок монотонного левого абриса */
if( left_lim==ll )
	left_lim=3;
return(broken_M_pen= ((dest>left_lim ||
  (dest>left_lim-2&&left_lim>5||dest==left_lim&&left_lim>4)&&incr>dy/2)
			&& fc<3 && maxd>3) );
}
/* descr_ce : дикриминатор 'Ц','ц' с очень короткими хвостами */
static INT descr_ce(BYTE *r,INT D_X,INT hy)
{
BYTE *rr=r+D_X;
INT i;
INT b1=LOCAL[0]-(LOCAL_W[0]>>1);
INT e2=LOCAL[1]+(LOCAL_W[1]>>1);
INT i1=SumIntervalBits(r+2*D_X,b1,(INT)(e2+1))/3;
INT num;
				/* заливка 1-ой снизу линии             */
INT i2=SumIntervalBits(r+D_X,b1,(INT)(e2+1))/3;
                                /* заливка 2-ой снизу линии             */
INT diap = e2-b1;               /* конец 2-ой ноги - начало 1-ой ноги   */

diap -= (diap>>3);		/* 7/8 					*/

if( i2>diap || i1>diap )        /* заливка начата во 2-ой или 3-ей линии*/
	return(1);
if( broken_flag )
	return(0);
for(num=i=0;i<hy;i++,rr-=D_X)
	{
	num+=(NumHorizInterval(rr,D_X)==2);
	if( SumIntervalBits(rr,b1,(INT)(e2+1))/3>=diap )
		{
		if( i>2 && num>=i-1 )
			return (1);/* по 2 интервала во всех строках i>=3 */
		else
			return(0);/* есть залитая линия                   */
		}
	}
return(1);                      /* в нижней зоне нет залитых линий      */
}


/*  DiskrJu : дискриминатор Ю (в среднем 3 интервала в каждом сечении) */
#ifdef INTERSEPTOR
static INT DiskrJu1(BYTE *RASTR,INT D_X,INT dx,INT dy)
{
BYTE *RASTER=RASTR;
INT i,ret,r,s2,s3,n,ddx;
BYTE inter[256],sum[256];
ddx = bytlen(dx);

for(n=s2=s3=i=0;i<dy; i++, RASTER+=D_X,n++ )
	{
  r =  NumHorizInterval(RASTER,ddx);
	s2 += (r==2);
	}
	/*  NumHorizInterval : число интервалов в строке */

n = dy/3;
ret = 0	;

if( s3<n ) ret += n - s3;
if( !broken_flag && s2==0 ) ret += 2;
for(RASTER=RASTR,i=0;i<dx;i++)
  {
  inter[i] = NumVertInterval(RASTER, D_X, dy, i);
  sum  [i] = VertSum(RASTER, D_X, dy, i);
  }

for(r=i=0;i<dx/4;i++)
    {
    r += (inter[i]==3);
    if( r>4 )
      return 5;
    }

if( ret && (s3>0||s2>0) )
  {
  for(r=1000,n=0,i=dx/4;i<(dx*3)/4;i++)
    if( r>sum[i] && inter[i]==1 )
      {
      r=sum[i];
      n=i;
      }


  for(r=0,i=n;i<dx;i++)
    {
    r += (inter[i]==2);
    }
  if( r>4 )
    ret=0;
  }
return  (ret) ;
}
#else
/*
static INT DiskrJu(BYTE *RASTR,INT D_X,INT dx,INT Ly)
{
BYTE *RASTER=RASTR;
INT i,ret,r,s2,s3,n;
dx = bytlen(dx);

for(n=s2=s3=i=0;i<Ly; i++, RASTER+=D_X,n++ )
	{
	r =  NumHorizInterval(RASTER,dx);
	s2 += (r==2);
	s3 += (r==3);
	}
  // NumHorizInterval : число интервалов в строке

n = Ly/3;
ret = 0	;
if( s3<n ) ret += n - s3;
if( !broken_flag && s2==0 ) ret += 2;
#ifdef UFA
if( ret && s3>3 )	ret = 1;
#endif
return  (ret) ;
}
*/
#endif

/* for letters 'ж' */
static INT DiskrJ0(BYTE *RASTR,INT D_X,INT dx,INT Ly,INT lim)
{
BYTE *RASTER=RASTR;
INT i,three,n,all,ret,one;
dx = bytlen(dx);
for(one=all=three=i=0;i<Ly; i++, RASTER+=D_X )
	{
	n = NumHorizInterval(RASTER,dx);
	/*  NumHorizInterval : число интервалов в строке */
	three += ( n==3 );
	all   += ( n>=3 );
	one   += ( n==1 );
	}

if( Ly>9 )
        {
	ret = (three<lim)?lim-three:0 ;
	if( all==Ly && lim>3 )	/* в середине */
                ret = 2;
        }
else
	{ /* маленькие ж */
	if( three>=lim )
		ret = 0;
	else
		ret = (all<lim)?lim-all:0 ;
	}
if( lim<=3 && ret && one+all>Ly-3 )
	ret=0;
return( ret );
}

static INT Diskr3(BYTE *RASTR,INT D_X,INT dx,INT Ly)
{
BYTE *RASTER=RASTR;
INT i,n,all,ret,one;
dx = bytlen(dx);
for(one=all=i=0;i<Ly; i++, RASTER+=D_X )
	{
	n = NumHorizInterval(RASTER,dx);
	/*  NumHorizInterval : число интервалов в строке */
	all   += ( n>=3 );
	one   += ( n==1 );
	}

ret = (all>3) ;
return( ret );
}



static int DiskrJ(unsigned char *RASTR,int D_X,int dx,int dy)
{
int i,t,tu,td,Ly=dy>>2,ly=dy-2*Ly,p,l=dy>>1;
dx = bytlen(dx);
for(tu=i=0;i<Ly; i++, RASTR+=D_X )
	tu += ( NumHorizInterval(RASTR,(BYTE)dx)==3 );
for(td=t=0;i<ly; i++, RASTR+=D_X )
        {
        p = NumHorizInterval(RASTR,(BYTE)dx);
	t += (p==1);
	if( i<l )
		tu += (p==3);
        if( i>l )
                td += (p==3);
        }
for(;i<dy; i++, RASTR+=D_X )
	td += ( NumHorizInterval(RASTR,(BYTE)dx)==3 );
		/*  NumHorizInterval : число интервалов в строке */
return	(
	tu>3 && t>=2 && td>3 ||
	tu>1 && t>2 && td>1 && tu+td>3
	);
}

/* for letters 'ш' */
static INT DiskrSh(BYTE *RASTR,INT D_X,INT dx,INT Ly)
{
BYTE *RASTER=RASTR;
INT i,num,n2,p,ddx;
ddx = bytlen(dx);
for(n2=num=i=0;i<Ly; i++, RASTER+=D_X )
	{
	p=NumHorizInterval(RASTER,ddx);
	/*  NumHorizInterval : число интервалов в строке */
	num += ( p!=3 );
	n2 += (p==2 );
	}

if( n2 )
{	/* есть двухинтервальные строки */
INT b=(LOCAL[0]+LOCAL[1])/2,dd=(LOCAL[1]-LOCAL[0])+(LOCAL_W[1]+LOCAL_W[0])/2;
i = Ly<<1;
i = Ly/3-(Ly>>2);
Ly -= i;
for(RASTER=RASTR+D_X*i;i<Ly;i++, RASTER+=D_X)
	{
	p =  SumIntervalBits(RASTER,b,dx)/3;
	if( p>=dd && NumHorizInterval(RASTER,ddx)==2 )
		return 4;
	}
}
return( num>2?num-2:0 );
}

/* for letters 'ш' */
static INT DiskrSh0(BYTE *RASTR,INT D_X,INT dx,INT dy,INT dx0)
{
BYTE *RASTER=RASTR+D_X*(dy-(dy>>2));
INT i,num,l=dx0-(dx0>>2);
if( lower_long_line<0 )
{
dx = bytlen(dx);
for(num=0,i=dy-(dy>>2);i<dy; i++, RASTER+=D_X )
	num += ( NumHorizInterval(RASTER,dx)==1 && SumBits(RASTER, dx)>l );
		/*  num : число строк с одним длинным интервалом */
lower_long_line=num;   /* число залитых строк */
}
return( lower_long_line );
}

/*  DiskrLeft : есть ли дыра справа ? */
INT DiskrLeft(BYTE *RASTR,INT D_X,INT dx,INT dy, INT L)
{
INT sum,p,x,i,Ly,p_old,curr_sum,h;
INT minr,maxr;
BYTE *RASTER=RASTR+D_X*(dy>>2),*R;
if( left_dist[L]>=0 )
	return( left_dist[L] );
Ly=dy-2*(dy>>2);
h=Ly;
R=RASTER;

MinMaxLeft(RASTER,D_X,(BYTE)dx,(BYTE)Ly,&minr,&maxr);
if( minr && maxr )
	{
	minr--; maxr--;
	}
x = maxr - minr;
if( minr>(dx>>1) )
	{
  left_max = maxr-minr;
	left_line=0;
	return( (left_dist[L]=1) );
	}
left_dist[L]=(x>=L);
if( left_dist[L] )              /* big hole */
	{
        left_line=0;
	if( dy>17 )
	while( VertSum(R,D_X,h,minr)<(dy>>2) && minr<maxr)minr++;
	for(p_old=-1,curr_sum=sum=0,i=minr ; i<=maxr ; i++ )
		{
		p = NumVertInterval(R, D_X, h, i);
		if( p>=2 )
			{          /* начало серии 2-интервальных столбцов */
			if( p_old!=2 )
				curr_sum=1;
			else curr_sum++;  /* накопление ширины дырки */
			if( curr_sum>L )break;
                        }
		else if( p_old>=2 )
			{      /* конец серии 2-интервальных столбцов */
			if(  curr_sum>sum )
				sum=curr_sum;
			if( sum>=L )break;
			}
		p_old=p;
		}
	if( sum==0 && curr_sum )
		sum = curr_sum;
	left_dist[L]=( sum>=L); /* hole */
	}
else
	left_line=1;
left_max = maxr-minr;
return( left_dist[L] );
}

/*  DiskrLeftBig : есть ли бльшая дыра слева ? */
INT DiskrLeftBig(BYTE *RASTR,INT D_X,INT dx,INT dy, INT L)
{
INT sum,p,x,i,Ly,p_old,curr_sum,h;
INT minr,maxr;
BYTE *RASTER=RASTR+D_X,*R;
if( left_dist_big[L]>=0 )
	return( left_dist_big[L] );

Ly=dy-2;
h =  dy ;
R =  RASTR;

MinMaxLeft(RASTER,D_X,(BYTE)dx,(BYTE)Ly,&minr,&maxr);
if( minr && maxr )
	{
	minr--; maxr--;
	}
x = maxr - minr;
left_dist_big[L]=(x>=L);
if( left_dist_big[L] )              /* big hole */
	{
	if( dy>17 )
	while( VertSum(R,D_X,h,minr)<(dy>>2) && minr<maxr)minr++;
	for(p_old=-1,curr_sum=sum=0,i=minr ; i<=maxr ; i++ )
		{
		p = NumVertInterval(R, D_X, h, i);
		if( p>=2 )
			{          /* начало серии 2-интервальных столбцов */
			if( p_old!=2 )
				curr_sum=1;
			else curr_sum++;  /* накопление ширины дырки */
			if( curr_sum>L )break;
			}
		else if( p_old>=2 )
			{      /* конец серии 2-интервальных столбцов */
			if(  curr_sum>sum )
				sum=curr_sum;
			if( sum>=L )break;
			}
		p_old=p;
		}
	if( sum==0 && curr_sum )
		sum = curr_sum;
	left_dist_big[L]=( sum>=L); /* hole */
	}

return( left_dist_big[L] );
}

/*  DiskrRight : есть ли дыра справа ? */
INT DiskrRight(BYTE *RASTR,INT D_X,INT dx,INT dy,INT L)
{
INT sum,p,x,dl,Ly,i,p_old,curr_sum,h;
INT minr,maxr,ddy;
BYTE *RASTER=RASTR+D_X*(dy>>2),*R;
if( right_dist[L]>=0 )
	return( right_dist[L] );

Ly=dy-2*(dy>>2);
h=Ly;
R=RASTER;

dl=(((dx+7)>>3)<<3);
ddy = dy>30 ? (dy>>3):(dy>>2);
MinMaxRight(RASTER,D_X,(BYTE)dx,(BYTE)Ly,&minr,&maxr);
x = maxr - minr;
if( maxr-((dx&7)?(8-(dx&7)):0)>(dx>>1) )
	{
  right_max = maxr-minr;
  right_line=0;
	return( (right_dist[L]=1) );
	}
right_dist[L] = ( x>=L );
if( right_dist[L] )       /* big hole */
	{
	right_line=0;
	if( dy>17 )
	while( VertSum(R,D_X,h,(BYTE)(dl-minr))<ddy && minr<maxr)minr++;
	for(p_old=-1,sum=curr_sum=0,i=minr ; i<=maxr ; i++ )
		{
		p = NumVertInterval(R, D_X, h, (BYTE)(dl-i));
		if( p>=2 )
			{          /* начало серии 2-интервальных столбцов */
			if( p_old<2 )
				curr_sum=1;
			else curr_sum++;  /* накопление ширины дырки */
			if( curr_sum>L )break;
                        }
		else if( p_old>=2 )
			{      /* конец серии 2-интервальных столбцов */
			if(  curr_sum>sum )
				sum=curr_sum;
			if( sum>=L )break;
			}
		p_old=p;
		}
  if( sum==0 && curr_sum )
		sum = curr_sum;
	right_dist[L]=( sum>=L); /* hole */
	}
else
	right_line=1;

right_max = maxr-minr;
return( right_dist[L] );
}

/*  DiskrRightBig : есть ли большая дыра справа ? */
INT DiskrRightBig(BYTE *RASTR,INT D_X,INT dx,INT dy,INT L)
{
INT sum,p,x,dl,Ly,i,p_old,curr_sum,h;
INT minr,maxr;
BYTE *RASTER=RASTR+D_X,*R;
if( right_dist_big[L]<0 )
{
Ly=dy-2;
h =  dy ;
R =  RASTR;

dl=(((dx+7)>>3)<<3);
MinMaxRight(RASTER,D_X,(BYTE)dx,(BYTE)Ly,&minr,&maxr);
x = maxr - minr;
right_dist_big[L] = ( x>=L );
if( right_dist_big[L] )       /* big hole */
  {
  if( dy<13 || VertSum(RASTR, D_X, dy, (BYTE)(dl-minr))<dy-2)
	{
	if( dy>17 )
	while( VertSum(R,D_X,h,(BYTE)(dl-minr))<(dy>>2) && minr<maxr)minr++;
	for(p_old=-1,sum=curr_sum=0,i=minr ; i<=maxr ; i++ )
		{
		p = NumVertInterval(R, D_X, h, (BYTE)(dl-i));
		if( p>=2 )
			{          /* начало серии 2-интервальных столбцов */
			if( p_old<2 )
				curr_sum=1;
			else curr_sum++;  /* накопление ширины дырки */
                        if( curr_sum>L )
                          {
                          sum = curr_sum;
                          break;
                          }
                        }
		else if( p_old>=2 )
			{      /* конец серии 2-интервальных столбцов */
			if(  curr_sum>sum )
				sum=curr_sum;
			if( sum>=L )break;
			}
		p_old=p;
		}
        if( sum==0 && curr_sum )
		sum = curr_sum;
	right_dist_big[L]=( sum>=L); /* hole */
	}
	else   right_dist_big[L]=0;  /* no hole - vert line */
  }

} /* calc right_dist */
return( right_dist_big[L] );
}


/* for letters 'C','c','e' */
static INT DiskrVertCE(BYTE *RASTR,INT D_X,INT dx,INT dy,INT X,
                        BYTE let, BYTE inc)
{
BYTE *RASTER=RASTR;
INT i,p,n,s3,d=dx>>2,wid=bytlen(dx);
INT ody=dy>>2;
	BYTE *r=RASTR+ody*D_X;
	INT t1,t2,t3,num1,num2,num3,minnum,n2;
	INT l = dy -(ody<<1),num,z=dx-(dx>>3);
	INT nn[7];

if( c_or_e<0 )
	{
	d_c=0;
	/* горизонтальные исследования 	*/
	for(minnum=dx,n2=num=num1=num2=num3=0,i=ody;i<l; i++, r+=D_X )
		{
		t1=NumHorizInterval(r,wid);
		t2=SumBits(r, wid);
		if( t1==2 )
			{

			t3 = (wid<<3) - LeftDistance(r,wid)  -
					RightDistance(r,wid) - t2;
			if( n2>0 )
				{
				if( dx>10 && t3<3 )
					num3++;
				if( minnum>t3 )
					minnum=t3;
				}
			n2++;
			}
		num  += (t1==1 && t2>=z);
		num1 += (t1==1 && t2>=z-1);
		num2 += (t2>=z);
		}
		/*  num : число строк с одним длинным интервалом */
	if( num>1 || num1>2 || num2>3 || num3>1 )
		{		/* есть непрерывная перекладина */
		c_or_e = 1;     /* или набор залитых строк       */
		d_e = 0;
		d_c = num;
		if( num3 ) d_c += (minnum==1?4:3);
		return( (let==(BYTE)'е')?d_e:d_c );
		}
if( num==0 && num1==0  && num2==0 && dy<24 )
{       /* ищу прыщ напротив конца правого рога */
r=RASTR+ody*D_X;
t2 = dx>>1;
for(i=ody;i<l; i++, r+=D_X )
		{
		num1=SumIntervalBits(r,t2,dx);

		if( i>ody && num!=0 && num1==0 )
			break;
		num = num1;
		}
i -= 4;
r = RASTR+i*D_X;
for(t3=t2=0;t2<7;t2++,i++,r+=D_X)
	{
	nn[t2]=EndBlackInterval(r,wid);
	t3+=(NumHorizInterval(r,wid)==2);
	}
for(t1=t2=nn[0],num=0,num1=1;num1<7;num1++)
	{
	if( t1>nn[num1] && nn[num1]>=0 )
		t1=nn[num1];
	if( t2<nn[num1] )
		t2=nn[(num=num1)];
	if( t2==nn[num1] && num==0 )
		num=num1;
	}
for(num1=num-1;num1>=0;num1--)
	if( nn[num1]<t2 )
		break;
for(num2=num+1;num2<7;num2++)
	if( nn[num2]<t2 )
		break;
if( inc && t2-t1<3 )
  t2=t1;  // Oleg : ERECTION conditions : 09-08-95 09:47pm
if( t3>2 && t2>t1 && num1>=0 && num2<7 )
	{	/* вот прыщик */
	c_or_e = 1;     /* или набор залитых строк       */
	d_e = 0;
	d_c = 1+t2-t1;
	if( (let==(BYTE)'е') )
	return( d_e );
	}
}
	/* далее вертикальные исследования	*/

	dx-=d;
	X &= 7;
	for(n=s3=0,i=d;i<dx; i++)
		{
		p = NumVertInterval(RASTER, D_X, dy, (BYTE)(i+X));
		s3 += ( p==3 );
		if( p==3 || p==2 )n++;
		}
		/*  NumVertInterval : число линий в столбце */
	p =  n;
	n *= 4;
	n /= 10;  /* 40 % */
	p -= n;   /* 60 % */

	c_or_e = 1;
	d_e = (s3<p)?p-s3:0;
	if( s3==0 && d_e<3 )
		d_e = 4;
	d_c = MAX(d_c,(s3>n)?s3-n+1:0);
	}
return( (let==(BYTE)'е')?d_e:d_c );
}


static INT average_tl_angle(BYTE *RASTER, INT D_X, INT dx, INT dy,
				INT t)
{
if( av_tl<0 )
	av_tl=average_angle(RASTER,D_X,dx,(INT)(dy>>2),LeftDistance,t);
return(av_tl);
}

static INT average_bl_angle(BYTE *RASTER, INT D_X, INT dx, INT dy,
				INT t)
{
if( av_bl<0 )
	av_bl=average_angle(RASTER+D_X*(dy-(dy>>2)),
		D_X,dx,(INT)(dy>>2),LeftDistance,t);
return(av_bl);
}

static INT average_br_angle(BYTE *RASTER, INT D_X, INT dx, INT dy,
				INT t)
{
if( av_br<0 )
	av_br=average_angle(RASTER+D_X*(dy-(dy>>2)),
		D_X,dx,(INT)(dy>>2),RightDistance,t);
return(av_br);
}

static INT average_angle(BYTE *RASTER, INT D_X, INT dx, INT dy,
			 INT  (*Distance)(BYTE *, INT), INT t)
{
INT i=0,n,p,H;
if( t==0 )
{       /* при t=0 срезаем массивные строки - ищем корни */
while( SumBits(RASTER,(BYTE)bytlen(dx))>(dx>>1) && i<dy )
	{
	i++;
	RASTER+=D_X;  /* black strings */
	}
}
for(H=n=0;i<dy; i++,RASTER+=D_X)
	if( (p=Distance(RASTER,(BYTE)bytlen(dx)))>=0 )
		{
		H++;
#ifdef UFA
		if( n==0 && i==dy-1 )
			continue;
#endif
		n+=p; /* nonzero string */
		}
return(H?n/H:-1);
}

static INT NoSymmLastColumn(BYTE *raster,INT D_X,INT Dx,INT dy)
{
INT up,down,col=Dx-1,h=dy>>1;
up   = VertSum(raster,D_X,h,col);
down = VertSum(raster+D_X*h,D_X,(INT)(dy-h),col); /* последний столбик */
if( up+down==1 )
        {
        col--;
        up   = VertSum(raster,D_X,h,col);
        down = VertSum(raster+D_X*h,D_X,(INT)(dy-h),col); /* последний столбик */
        }
if( dy<15 )
	{	/* кегль 6 */
        return( (down>2 && down>up+2) || (down>1 && up==0 ) );
	}
if( up+down<=3 )
	{
	col --;
        up   = VertSum(raster,D_X,h,col);
	down = VertSum(raster+D_X*h,D_X,(INT)(dy-h),col);
	}                                   /* предпоследний столбик */
return( down>3 && down>up+2 );  /* внизу больше чем наверху */
}

INT fill_center_zone(BYTE *raster,INT D_X,INT dy,
      INT beg, INT end, INT II)
{
INT i,num,l,ny,d=((end-beg)>>1),p, white, w;
BYTE *r=raster;

#ifdef INTERSEPTOR
end--;beg++;
d=((end-beg)>>1);
#endif

if( fill_center>=0 )
	return( fill_center );

p = (end-beg>3 );
if( rotate )    p=0; // OLEG : ERECTION CONDITION
white=end+p-beg+1;

for(ny=num=i=0;i<dy;i++,r+=D_X)
	{
	l = SumIntervalBits(r,beg,(INT)(end+p))/3;
	if( i==0 && l>=d )
		continue;
  w = end+p-beg-l;
	if( white>w )
    white=w;
  if( l )
		{
		num += l;
    if( l>d )
			num+=l;
    ny++;
		}
	}

if( ny  )
	{
  if( !(rotate && (dnri_hook||II) ) )
		{
		if( end - beg < 5 )
			fill_center = ( num>ny ) ;
		else
			fill_center = ( num>(ny<<1) );
		}
	else
		{
		fill_center = 0;
    if( rotate )
      {
      if( white<2 && dnri_hook )
        fill_center = 1;
      else if( d>2 && white<d )
        fill_center = 1;
      }
		}
	}
else
	fill_center = 0;
return( fill_center );
}

/* корректность слития крыши и нижних серифов для 'П','п' */
INT up_down_zones(BYTE *raster, INT D_X, INT dx, INT dx0,
			INT start1, INT stop1,
			INT start2, INT stop2)
{
INT i,num1,num2,l=dx0-(dx0>>3);
BYTE *r=raster;
if( up_down_serif>=0 )
	return( up_down_serif );

l = MIN(l,dx0-2);
dx = bytlen(dx);
for(r=raster+start1*D_X,num1=0,i=start1;i<stop1;i++,r+=D_X)
	{
	num1 += ( NumHorizInterval(r,dx)==1 && SumBits(r, dx)>=l );
		/*  num1 : число строк с одним длинным интервалом на крыше */
	}

for(r=raster+start2*D_X,num2=0,i=start2;i<stop2;i++,r+=D_X)
	{
	num2 += ( NumHorizInterval(r,dx)==1 && SumBits(r, dx)>=l );
		/*  num2 : число строк с одним длинным интервалом внизу */
	}

if( num1==0 && num2>=1   ) /* нижние серифы слиплись, а крыша разорвана */
	return( (up_down_serif=2) );
if( num1==0 && num2==0   ) /* две палки */
	return( (up_down_serif=1) );

return( (up_down_serif=0) );
}

/* корректность слития крыши и нижних серифов для 'В','в' */
INT up_down_zones_for_B(BYTE *raster, INT D_X, INT dx, INT dx0,
			INT start1, INT stop1,
			INT start2, INT stop2)
{
INT i,num1,num2,p,l=dx0-(dx0>>1);
BYTE *r=raster;
if( up_down_serif_B>=0 )
	return( up_down_serif_B );

dx = bytlen(dx);
l = MIN( l, dx0-2);
for(r=raster+start1*D_X,num1=0,i=start1;i<stop1;i++,r+=D_X)
	{
	p = NumHorizInterval(r,dx);
	if( p==1 && SumBits(r,dx)>=l )
		break;
	num1 += ( p==2 && i>0 );
		/*  num1 : число строк с двумя интерваламм на крыше */
	}

for(r=raster+(stop2-1)*D_X,num2=0,i=stop2-1;i>=start2;i--,r-=D_X)
	{
	p = NumHorizInterval(r,dx) ;
	if( p==1 && SumBits(r,dx)>=l )
		break;
	num2 += ( p==2 && i<stop2-1);
		/*  num2 : число строк с двумя интервалами внизу */
	}

up_down_serif_B = (num1>2)+(num2>2);
return( up_down_serif_B );
}

/***************************************************************************/
/*                                                                         */
/*   возвращает   1   если   слитие   'i'  с   'д'                         */
/*   возвращает   0   иначе                                                */
/*                                                                         */
/***************************************************************************/
static INT DiskrTsh(BYTE *RASTR,INT D_X,INT dx,INT dy,INT Dx)
/***************************************************************************/
/****     *RASTR     указатель   на  масив  с  учетом  пропуска     ********/
/****			      первой  строчки                       ********/
/****      dx        количество  битов  в  строке                   ********/
/****	   dy        kоличество  строк                              ********/
/****      D_X       количество  байтов  в  строке                  ********/
/****      Dx        количество  битов  в  строке  с  учетом        ********/
/****			      пропуска   первых  битов              ********/
/***************************************************************************/
{  BYTE  j,n4=dy>>2,bool_foot=1;
   BYTE  bit0,bit1,bit2;
   INT            i,fine=0;
   BYTE  *RAST;

/****************   проверка   наличия   двух  хвостиков  ******************/


   for (RAST=RASTR+(dy-3)*D_X,i=dy-3;;i--,RAST-=D_X){
      j=SumIntervalBits( RAST,(INT)0,(INT)dx )/3 ;
      if(  (j > 5*D_X) || (i<2*n4) ) break;
      j=(BYTE)NumHorizInterval( RAST, D_X );
      if( j > 1 )  fine+=20;
   }
   if( fine < 30 ){     return ( 0 );   }

/****************          положение      ног             ******************/

   bit0 = LOCAL[0] ;
   bit1 = LOCAL[1] ;
   bit2 = LOCAL[2] ;

/************   проверка   слития   в  верхнем   левом   углу  *************/

fine=0;
   for (RAST=RASTR,i=0;i<n4;i++,RAST+=D_X){
      j=SumIntervalBits(RAST,(INT)bit0,(INT)bit1)/3;
      if( j >  3*(bit1-bit0)/5 )    fine+=20;
      if( j == (bit1-bit0) )        goto end;
   }
   if( fine < 40 )   { goto   bbb;}/*razriv */

/******************  делает   гистограмму   ********************************/

   FOOT_A(RASTR, D_X, (BYTE)Dx, (BYTE)n4); bool_foot=0;

   for(i=bit0+1;i<bit1+1;i++){
      if(BUFFER[i]==0)  goto   bbb;/*razriv */
   }
   goto   end;/* slilos */

/************   проверка   слития   в  верхнем   правом   углу  ************/

bbb:fine=0;
   for (RAST=RASTR,i=0;i<n4;i++,RAST+=D_X){
      j=SumIntervalBits(RAST,(INT)bit1,(INT)bit2)/3;
      if( j >  3*(bit2-bit1)/5 )  	 fine+=20;
      if( j == (bit2-bit1) )             {  return(1); }
   }
   if( fine < 40 )   goto   end;/*razriv */

/******************  делает   гистограмму   ********************************/

   if( bool_foot ) FOOT_A(RASTR, D_X, (BYTE)Dx, (BYTE)n4);
   for(i=bit1+1;i<bit2+1;i++){
      if(BUFFER[i]==0)  goto   end;/*razriv */
   }
   return( 1 );/* slilos */

end: return ( 0 );

}  /* DiskrTsh */

INT small_density(BYTE *RAST,INT n,INT D_X,INT bw)
{
INT i,l,w,d;
INT b = bw << 3;

if( !omni && font_type==0 )
	return(1);

for(l=i=0;i<n;i++,RAST+=D_X)
	{
	w = b - RightDistance(RAST,bw) - LeftDistance(RAST,bw);
	d = SumBits(RAST,bw);
	l += (d>w-2);
	}

return( l<=(n/3) );
}

INT no_serific(BYTE *RASTR,INT dy,INT dx,INT wb)
{
INT l0=VertSum(RASTR,wb,dy,0);
INT l1=VertSum(RASTR,wb,dy,1);
INT l2=VertSum(RASTR,wb,dy,2);
INT r0=VertSum(RASTR,wb,dy,(INT)(dx-1));
INT r1=VertSum(RASTR,wb,dy,(INT)(dx-2));
INT r2=VertSum(RASTR,wb,dy,(INT)(dx-3));
dy -= 2;
if( l0<dy && l1<=dy && l1>dy-2 && l2>dy )
	l1=l2;
if( r0<dy && r1<=dy && r1>dy-2 && r2>dy )
	r1=r2;
return ( l0>dy || l1>dy ) && ( r0>dy || r1>dy ) ;
}

INT vert_stairs(INT arr[], INT lim)
{
INT i,old,jmp;
for(jmp=0,i=1,old=arr[0];i<lim;i++)
	{
	if( arr[i]==-1 )
		continue;
	if( old<arr[i] )
		jmp++;
	if( old>arr[i] )
		return 0;
	old = arr[i];
	}
return ( jmp );
}

/***************************************************************************/
/*                                                                         */
/*  возвращает   оценку возрастания середин интервалов перкладины ИН       */
/*                                                                         */
/***************************************************************************/
static void DiskrIN(BYTE *RASTR,INT D_X,INT dy,INT bw,INT dx)
/***************************************************************************/
/****     *RASTR     указатель   на  массив                         ********/
/****	   dy        kоличество  строк                              ********/
/****      D_X       количество  байтов  в  строке                  ********/
/***************************************************************************/
{  BYTE  n[256],hist[256];
   INT   ua[256],da[256];
   INT  i,n2=dy-2*(dy>>2),n4,mean,fine;
   INT 	incr,decr,old,neue,equ;
   INT  l=beg2-end1-1,l_real,t,jump,rmin,rmax;
   INT  ol=1,or=1;	/* зазор слева и справа */
   BYTE *RAST ,*R;


n4 = MAX(dy/4,(LOCAL_W[0]+LOCAL_W[1])/4);
if( n4>dy/3 ) n4=dy/4;
n2 = dy - (n4<<1);
RAST = RASTR+D_X*n4;

if( IN_dis>0 )
	return;
IN_IN_Monus=0;
IN_pics=1;
IN_M=0;

if( l+ol+or<2 && dy>19 )
	{
	if( small_density(RAST,n2,D_X,bw) )
		{			/* нет заливки */
		IN_N=4;
		IN_I=2;
		}
	else
		{			/* заливка	*/
		IN_N=4;
		IN_I=3;
		}
	IN_dis=1;
	IN_equ=0;
	return;
	}

memset(hist,0,dy);
if( l<3 )
	{	/* отменить зазоры */
	or=ol=0;
	l=beg2-end1+1-ol-or;
	}
if( l>3 )
{
INT up_space=-1, down_space=-1;
INT up_fill=0,down_fill=0,d;
for(R=RAST,i=n4;i<=dy-2;i++,R+=D_X)
	{
	d=SumIntervalBits(R,(INT)(end1+ol),(INT)(beg2-or+1))/3;
	hist[i]=(BYTE)d;
	if( d==l && !up_fill )
		up_fill=i;
	if( d==l && i<n4+n2 )
		down_fill=i;
	}

if( up_fill && down_fill && up_fill>n4 &&
	(hist[up_fill-1]==0||hist[up_fill-2]==0) &&
	(hist[down_fill+1]==0||hist[down_fill+2]==0) )
	{
	IN_N=3;
	IN_I= 2;
	IN_dis=1;
	IN_equ=1;
	return;
	}

for( old=hist[n4],i=n4+1;i<=n2;i++)
	{
	neue = hist[i];
	if( up_space==-1 )
	if( old==1 && neue>=l && hist[i+1]>=l ||
	    old==0 && neue>=l-1 && hist[i+1]>=l )
	    {
	    if( NumHorizInterval(RASTR+D_X*(i+1),bw)==1 )
        {
        INT j,d;
        up_space = (neue==l ? 0 : 1);

        for(j=i+1;j<dy-2 && hist[j]>=l-1;j++);
        if( j<dy-2 )
          {
          for(d=0;j<dy-2;j++)
            d+=(hist[j]<hist[j-1]);
          if( d>2 )
            {
            up_space=-1;
            break;
            }
          if( d<3 )
            {
            down_space=0;
            break;
            }
          }
      }
  }
	if( down_space==-1 )
	if( neue==1 && old>=l && hist[i-2]>=l ||
	    neue==0 && old>=l-1 && hist[i-2]>=l )
	    {
	    if( NumHorizInterval(RASTR+D_X*(i-2),bw)==1 )
        down_space = (old==l ? 0 : 1);
	    }
	old = neue;
	}

if( up_space!=-1 && down_space!=-1 )
	{
	IN_N=3;
	IN_I= MIN(up_space,down_space);
	IN_dis=1;
	IN_equ=2;
	return;
	}
memset(hist,0,dy<<1);
} /* end of horiz study */

if( no_serific(RASTR,dy,dx,bw) )
	{
	n4 = dy>17 ? 4 : 2;
	n2 = dy - (n4<<1);
	RAST = RASTR+D_X*n4;
	}
memset(ua,0xFF,dy<<1);
memset(da,0xFF,dy<<1);
i = end1+ol-1;
n[i] = (BYTE)CenterVertInterval( RAST, D_X, n2, i,&ua[i],&da[i] );
				/* запасной левый отсчет 		*/
for(mean=l_real=0,i=end1+ol;i<=beg2-or;i++)
	{	/* таблица отчетов середин вертикальных интервалов 	*/
	n[i] = (BYTE)CenterVertInterval( RAST, D_X, n2, i,&ua[i],&da[i] );
	mean += n[i];
	if( n[i] )              /* mean	  - сумма   отсчетов		*/
		l_real++;	/* l_real - число ненулевых отсчетов 	*/
	}
n[i] = (BYTE)CenterVertInterval( RAST, D_X, n2, i,&ua[i],&da[i]);
				/* запасной отсчет 			*/
if( l!=l_real && (l_real==2 || (n[end1]|n[end1+1]) && (n[beg2]|n[beg2-1])) )
	{           	/* отсутствие перекладины 			*/
	IN_N_Bonus=2;
	IN_I_Bonus=2;
	if( l_real==2 )
		IN_P_Bonus=1;
	}
if( l_real<=1 && ((n[end1]==0&&n[end1+1]==0) || (n[beg2]==0&&n[beg2-1]==0)) )
	{           	/* отсутствие перекладины 			*/
	IN_N_Bonus=1;
	IN_P_Bonus=1;
	IN_I_Bonus=1;
	if( n[end1]==0 && n[end1+1]==0 && n[beg2]==0 && n[beg2-1]==0 )
		{
		IN_P_Bonus=2;
		IN_N_Bonus=1;
		IN_I_Bonus=1;
		}
	}

if( no_serific(RASTR,dy,dx,bw) )
	{	/* обратный пересчет в интервал высот [dy/4,dy-dy/4] */
	INT nn4,nn2,h;
	nn4 = MAX(dy>>2,(LOCAL_W[0]+LOCAL_W[1])>>1);
  if( nn4>dy/3 ) nn4=dy/4;
  nn2 = dy - (nn4<<1);
  RAST = RASTR+D_X*n4;
	for(mean=l_real=0,i=end1;i<=beg2;i++)
		{
		h = n2+n4-(n[i]>>1);
		if( h<nn4 || h>nn4+nn2 )
			n[i]=0;
		else
			{
			n[i] += ((nn2+nn4-n2-n4)<<1);
			if( n[i]>=(nn2<<1) )
				n[i]=0;
			else if( n[i] &&
				 (i!=end1||i==end1&&ol==0) &&
				 (i!=beg2||i==beg2&&or==0) )
				{
        mean += n[i];
				l_real++;
				}
			}
		}
	n2=nn2;
	n4=nn4;
	}
if( l_real<4 )
	 {
	 i = beg2-or+1;
	 if( or && n[i] && VertSum(RAST, D_X, n2, i)<n2-1 &&
		NumVertInterval(RAST, D_X, n2, i)==1 )
		{	/* учитываем последний отсчет */
		mean += n[i];
		or--;
		l_real++;
		l++;
		}
	 i = end1+ol-1;
	 if( ol && n[i] && VertSum(RAST, D_X, n2, i)<n2-1 &&
		NumVertInterval(RAST, D_X, n2, i)==1 )
		{	/* учитываем последний отсчет */
		mean += n[i];
		ol--;
		l_real++;
		l++;
		}
	 }
if( l_real<=1 )
{
INT dy1=n2/*dy>>1*/,nn,mm,mm1,minup,mindown,zaz;
BYTE *rrrr,*rrrr1;
zaz = beg2 - end1;
for(	minup=mindown=zaz, rrrr=RASTR, rrrr1=RASTR+(dy-1)*D_X, i=0;
	i<3;	i++, rrrr+=D_X, rrrr1-=D_X)
	{
	mm = zaz-SumIntervalBits(rrrr,end1,beg2)/3;
	if( minup>mm )
		minup = mm;
	mm1 = zaz-SumIntervalBits(rrrr1,end1,beg2)/3;
	if( mindown>mm1 )
		mindown = mm1;
	nn=dx-SumBits(rrrr,bw);
	if( nn<2 )
		break;
	}
if( i<3 || (minup*2<mindown && minup*3<zaz && zaz>3) )
	{ /* почти залитая крышка */
	IN_N_Bonus=IN_I_Bonus=1;IN_P_Bonus=2;
	}
else
	{
	if( (nn=n[end1+ol])>0 )
		{
		IN_N_Bonus=IN_I_Bonus=IN_P_Bonus=1;
		if( abs(nn-dy1)<3 )
			IN_N_Bonus=2;
		else if( nn<dy1-2 )
			IN_I_Bonus=2;
		}
	else	if( (nn=n[beg2-or])>0 )
		{
		IN_N_Bonus=IN_I_Bonus=IN_P_Bonus=1;
		if( abs(nn-dy1)<3 )
			IN_N_Bonus=2;
		else if( nn>dy1+2 )
			IN_I_Bonus=2;
		}
	}
}
{
INT z=beg2-end1+1;
if( z>4 && l_real*2>z )
	IN_IN_Monus=1;	/* А перекладины разрыв то маленький ! */
if( 	l_real>4 	|| 	l-l_real<=3 && l>5 ||
	l_real==4 && fill_center ||
	l_real<2 && z<4 && n4<6 ||
	z>10 && l_real<3 )
	{
	IN_P_Bonus=IN_I_Bonus=IN_N_Bonus=0;
	}

}

if( l_real>1 )
	{
	for(i=end1+ol;i<=beg2-or;i++)
		if( (neue=n[i])!=0 )
			hist[ neue ]++;

	mean=mean/l_real+((mean%l_real)>(l_real>>1));
				/* mean	  - средний отсчет		*/

	if( hist[mean-1]>l_real-2 )
		mean--;
	if( hist[mean+1]>l_real-2 )
		mean++;

if( l_real!=l && !(l_real==l-1 && (n[end1]==0||n[beg2]==0) ) )
if( !fill_center && l_real<=4 || l_real<=3 )
	{
	INT an[2],en[2],ll,dy1=n2,san[2],sen[2],z;
	/* поиск прыщей от 'Н' на середине высоты */
	an[0]=n[end1];
	an[1]=n[end1+1];
	en[0]=n[beg2-1];
	en[1]=n[beg2];
	for(ll=i=0;i<2;i++)
		{
		sen[i]=n[beg2-i];
		san[i]=n[end1+i];
		if( an[i]>0 )
			{
			if( abs(an[i]-dy1)>2 )
				an[i]=-1;
			else
				n[end1+i]=(BYTE)dy1,ll++;
			}
		if( en[i]>0 )
			{
			if( abs(en[i]-dy1)>2 )
				en[i]=-1;
			else
				n[beg2-i]=(BYTE)dy1,ll++;
			}
		}
	if( IN_I_Bonus==2 && ll==1 )
		IN_I_Bonus=1;
	if( ll>2 || ll==2 && broken_flag )
		{
		for(i=0;i<2;i++)
			{
			if( an[i]>0 )
				n[end1+i]=(BYTE)dy1;
			if( en[i]>0 )
				n[beg2-i]=(BYTE)dy1;
			}
		mean =  dy1;
		fill_center=1;
		IN_N_Bonus=2;
		IN_P_Bonus=IN_I_Bonus=0;
		}
	else
		{
		for(i=0;i<2;i++)
			{
			n[beg2-i]=(BYTE)sen[i];
			n[end1+i]=(BYTE)san[i];
			}
	/* поиск прыщей от 'И' по разные стороны от середины высоты */
		an[0]=n[end1];
		an[1]=n[end1+1];
		en[0]=n[beg2-1];
		en[1]=n[beg2];
		for(ll=i=0;i<2;i++)
			{
			z=VertSum(RAST, D_X, n2, (INT)(end1+i));
			if( an[i]>0 && an[i]<dy1-2 && z<n4 )
				ll++;
			z=VertSum(RAST, D_X, n2, (INT)(beg2-i));
			if( en[i]>0 && en[i]>dy1+2 && z<n4)
				ll++;
			}
#ifndef INTERSEPTOR
    if( ll>2 || ll==2 && broken_flag && !rotate)
#else
    if( ll>3 || ll==2 && broken_flag && !rotate)
#endif
			{
			fill_center=1;
			IN_I_Bonus=2;
			IN_P_Bonus=IN_N_Bonus=0;
			}
		}
	}
else
{
if( fill_center && l_real>l-3 && l>2 )
{
INT lim = (beg2-or-end1+ol)>>1;
for(t=0,i=end1+ol;i<=lim;i++)
	if( n[i]>((n2-2)<<1) )
		t++;
	if( t>=MAX(2,(l_real>>1)) )
	{		/* перекладина слишком высоко 			*/
	fill_center=0;	/* коррекция штрафа за отстутствие перекладины 	*/
	IN_N=4;
	IN_I=1;
	IN_dis=1;
	return;
	}
}

if( fill_center && l_real<2 && l>4 )
	{               /* полное отсутствие перекладины 		*/
	fill_center=0;	/* коррекция штрафа за отстутствие перекладины 	*/
	IN_N=4;
	IN_I=1;
	IN_dis=1;
	return;
	}
}


for(old=incr=decr=fine=0,i=end1+ol,rmin=dy,rmax=0;i<=beg2-or;i++)
	if( (neue=n[i])!=0 )
		{	/* fine - сумма расстояний от среднего 	*/
		if( old==0 )
			old = neue;/* первый ненулевой отсчет	*/
		if( neue>rmax )
			rmax=neue;
		if( neue<rmin )
			rmin=neue;
		if( neue>mean )
			fine += neue - mean;
		else
			fine += mean-neue;
		if( neue>old )
			incr++;   /* число скачков возрастаний 	*/
		else if( neue<old )
			decr++;   /* число скачков убываний 	*/
		old = neue;
		}
if( fine && rmax-rmin<=2 && !(l_real==3 && incr==2) )
	fine=0;	/* все отсчеты в 2-х линиях */
if( fine && l_real==3 && incr==2 )
	fine+=2;	/* 2 скачка в 3-х столбцах */

if( omni ){
INT fin=fine,inc=incr,dec=decr;

neue = n[end1];
if( ol && neue && neue<n[end1+1] )
	{
	if( neue>mean )
		fin += neue - mean;
	else
		fin += mean-neue;
	inc++;   /* число скачков возрастаний 	*/
	}

neue = n[beg2];
if( or && neue && neue>n[beg2-1])
	{
	if( neue>mean )
		fin += neue - mean;
	else
		fin += mean-neue;
	inc++;   /* число скачков возрастаний 	*/
	}
/* большое сходство с 'И' */
if( fin>10 && inc>3 && dec<1  && LOCAL[0] <= dx/4)
	IN_M=80;
else if( fin>10 && inc>2 && dec==0 && LOCAL[0] <= dx/4)
	IN_M=80;
else
	IN_M=0;
	}
if( 	abs(incr-decr)<2 && 	/* близкие значения скачков 	*/
	(incr>1 &&              /* более 1 возрастания		*/
	decr>1 ||		/* более 1 убывания		*/
	incr && decr && incr+decr<4 ) &&	/* мало скачков */
	fine<=l			/* малая дисперсия		*/
  )
		fine=0;
if( incr<2   &&            /* маловато возрастаний   */
    l_real>4 &&            /* на широкой перекладине */
    decr && incr+decr<4 )  /* скачков немного        */
 fine=0;
	if( fine>2 && incr<2 && decr>1 && l>3 )
		fine -= 2;		/* всего 1 возрастание		*/
	t = (incr<=1)&&(decr<=1);
	for(i=end1+ol; n[i]==0 && i<=beg2-or;i++); /* skip empty columns */
	for(equ=incr=0,old=n[i++];i<=beg2-or;i++)
		{
		if( n[i] )
			neue=n[i];
		else
			continue;
		if( neue>old )
			incr += neue-old;
		old = neue;
		}
	if( t==0 )              /* более 1-го возрастания или убывания 	*/
		fine += incr ;	/* добавили штраф за возрастание	*/
	for(t=equ=i=0;i<dy;i++)
		if( hist[i]>equ )
			equ=hist[(t=i)];
	if( 	fine>1 && equ>2 && t==mean && or==0 && ol==0 &&
		n[end1]<mean && mean<n[beg2] && equ+2==l_real )
			fine=0;	/* 1-ый и последний скачки в	*/
				/* разорванном растре, интервал	*/
				/* постоянства длины 3		*/
	if( equ>1 && fine<6 )
		{
		INT fineold=fine;
		t = n4 + n2 - (t>>1);
		for( RAST=RASTR+D_X*(t-2),i=t-2;i<=t+2;i++,RAST+=D_X)
			if( SumIntervalBits(RAST,end1,(INT)(beg2+1))==
				(beg2-end1+1)*3 )
				{		/* есть перекладина */
				fine=0;
				break;
				}
		if( equ==2 && (ol&&n[end1+ol] || or&&n[beg2-or]) )
			fine=fineold;
		}

	if( l_real<5 && equ>2 )
		fine=0;		/* 3 из 4(или <4) совпадают 		*/
	if( l_real>4 && equ>l_real-2 )
		fine = 0;	/* совпадают l-1 из l отсчетов		*/
	jump=0;
	if( equ==l-1 )
		{		/* единственный всплеск			*/
		i=end1+ol;
		if( n[i]!=0 && n[i]<n[i+1] && n[i+2]==n[i+1] )
			{
			fine=0;	/* единственный левый всплеск		*/
			jump=1;
			}
		else
			{
			i=beg2-or;
			if( n[i-1]!=0 && n[i]>n[i-1] && n[i-2]==n[i-1] )
				{
				fine=0;
				/* единственный правый всплеск		*/
				jump=1;
				}
			}
		}
if( l_real>2 )
	{		/* нормировка накопленного штрафа 	*/
	fine <<= 5;     /* *32 ?????????????			*/
	fine /= l_real; /* истинная ширина 			*/
	fine /= n2;     /* высота				*/
	}

	}
else
	{
	fine=0; 	/* l_real<2 : не можем оценить образ 	*/
	IN_dis=1;
	IN_equ=IN_N=0;
	IN_I=3;
	IN_pics=0;
	if( fill_center && l>2 )
		fill_center=0;	/* коррекция штрафа за отстутствие перекладины */
	if( 	!fill_center && l_real==1 &&
		(NumVertInterval(RAST, D_X, n2, end1)==1 &&
		 VertSum(RAST,D_X,n2,end1)<n4 &&
		 n[end1] && abs(n[end1]-(dy>>1))<3 ||
		 NumVertInterval(RAST, D_X, n2, beg2)==1 &&
		 VertSum(RAST,D_X,n2,beg2)<n4 &&
		 n[beg2] && abs(n[beg2]-(dy>>1))<3) )
		fill_center=2;

	return;
	}

IN_N=IN_I = fine;	/*           штраф за возрастание 	*/
if( incr<2 && l_real>5 && decr>4 )
	{
	if( fine>6 )
		IN_N=5;
	IN_I=1;   /* similar to N */
  }
if( incr<1 && l_real>3 && decr>l_real/2 )
	{
  IN_N=6;
	IN_I=1;   /* similar to N */
  }
if( fine==0 && jump )
	IN_I=3;
if( !fill_center && (l_real>3 || l_real>l-3) && l>2 && mean*4<dy*3 )
	{
	if( l_real>2 || n[end1] && n[beg2] )
#ifdef INTERSEPTOR
  if( l_real>5 )
#endif
  if( !rotate || l_real>3 )
  fill_center=1;  /* коррекция штрафа за отстутствие перекладины */
	}
if( fine>5 && l_real==2 && !broken_flag && incr==0 && decr==1 )
	{
	IN_N=4;
	IN_I=2;
	fill_center=0;
	}
IN_dis=1;
equ -= l-2;
IN_equ = (equ>0)?2+equ:0;	/* IN_equ -штраф за постоянство */

if( DiskrHorizIN(RASTR,D_X,dy) )
			{   /* жирная перекладина */
			IN_N=3;
			IN_I=2;
			}
if( omni )
	{	/* 'И' путается с 'М' */
	INT i,le,ri,nnn=(beg2+end1+ol-or)/2;
	if( fine>15 && decr>3 || fine>20 && decr>2 ||
	    fine>10 && incr<1 && decr>3 )
		IN_I=1;
	if( l_real>4 && fine>9 )
	{
	for(old=n[end1+ol],le=0,i=end1+ol;i<nnn;i++)
		{
		neue = n[i];
		if( neue )
			{
			if( neue<old )
				le++;
			old=neue;
			}
		}
	for(old=n[i],ri=0;i<beg2-or;i++)
		{
		neue = n[i];
		if( neue )
			{
			if( neue>old )
				ri++;
			old=neue;
			}
		}
	if( le>3 && ri>3 )
		IN_I=1;
	}
	}

{
INT up_skip=vert_stairs(&ua[end1],(INT)(beg2-end1+1));
INT down_skip=vert_stairs(&da[end1],(INT)(beg2-end1+1));

if( IN_I<=3 )
if( up_skip>3 && down_skip>3 ||
    up_skip>1 && down_skip>1 && up_skip+down_skip>4 )
	{
	IN_N=4;
	IN_I= 4;
	IN_dis=1;
	IN_equ=0;
	return;
	}
}

return;
} 			/* 		DiskrIN 		*/

/***************************************************************************/
INT DiskrHorizIN(BYTE *RASTR,INT D_X,INT dy)
/***************************************************************************/
/****     *RASTR     указатель   на  массив                         ********/
/****	   dy        kоличество  строк                              ********/
/****      D_X       количество  байтов  в  строке                  ********/
/***************************************************************************/
{  BYTE n[256];
   INT  i,j,n2=dy-2*(dy>>2),n4=dy>>2,imax,nmax,kmax;
   INT l = beg2 - end1 ,h;
   BYTE *RAST = RASTR+D_X*n4;


if( IN_horiz_dis>=0 )
	return(IN_horiz_dis);

if( l<4 )
	{ /* малое расстояние */
	IN_horiz_dis=0;
	return(IN_horiz_dis);
	}

for(imax=nmax=kmax=-1,i=n4,j=0;j<=n2;j++,i++,RAST+=D_X)
	{	/* заливки линий 	*/
	n[i] = SumIntervalBits(RAST,end1,beg2)/3;
	if( n[i]>nmax )
		{
		nmax = n[i];
		imax = i;
		kmax=1;
		}
	else if( n[i]==nmax )
		kmax++;
	}

if( imax>0 && nmax==l && kmax>1 )
	{
	for(i=imax;n[i]==nmax;i--);
	h = ( n[i-1]==0 && n[i]<3 || n[i]<2 ) ;
	for(i=imax;n[i]==nmax;i++);
	l = ( n[i+1]==0 && n[i]<3 || n[i]<2 ) ;
	}
else
	l=h=0;

return (IN_horiz_dis= (h&&l) ) ;
} 			/* 		DiskrHorizIN 		*/

static INT DiskrEZ(BYTE *RASTR,INT D_X,INT dx,INT dy)
/***************************************************************************/
/****     *RASTR     указатель   на  масив  с  учетом  пропуска     ********/
/****			      первой  строчки                       ********/
/****      dx        количество  битов  в  строке                   ********/
/****	   dy        kоличество  строк                              ********/
/****      D_X       количество  байтов  в  строке                  ********/

/*  return   1  for   З    */
/*      2  for   Э    */

/***************************************************************************/
{  BYTE  j;
   INT n4=dy>>2,n2=dy>>1;
   BYTE  j1,j2,j3,j4;
   INT            i;
   BYTE  *RAST,*r1,*r2;

if( diskr_EZ>=0 )
	return ( diskr_EZ);
diskr_EZ=0;
   dx-=2;
   for (RAST=RASTR+n4*D_X,i=0;i<n2;i++,RAST+=D_X)
     {
        j=(BYTE)SumIntervalBits( RAST,2,dx ) ;
        if( j>9 ) {  r1=RAST; break; }
      }
   if( i==n2 )           return(0);        /* не  определ  перекл */

   for (RAST=RASTR+(dy-n4)*D_X,i=0;i<n2;i++,RAST-=D_X)
     {
      j=(BYTE)SumIntervalBits( RAST,2,dx ) ;
      if( j>9 )   {  r2=RAST; break; }
     }
   if( i==n2 )           return(0);        /* не  определ  перекл */

   j1=(BYTE)SumIntervalBits( r1-  D_X,2,dx );
   j2=(BYTE)SumIntervalBits( r1-2*D_X,2,dx );
   j3=(BYTE)SumIntervalBits( r2+  D_X,4,dx );
   j4=(BYTE)SumIntervalBits( r2+2*D_X,4,dx );

   j1 = (j1-j2>=3 );
   j3 = (j3-j4>=3 );



   if( j1 && j3 )
	diskr_EZ=2; /* 2 ступеньки */

   if( (!j1) && (!j3) )
	diskr_EZ=1;  /* нет ступенек */

   return(diskr_EZ);        /* неопределенность */
}  /* DiskrEZ */

static INT horiz_density(BYTE *RAST,INT D_X,INT dx,INT beg,INT end)
/***************************************************************************/
/****     *RAST      указатель   на  масив  с  учетом  пропуска     ********/
/****			      первой  строчки                       ********/
/****      dx        количество  битов  в  строке                   ********/
/****	   dy        kоличество  строк                              ********/
/****      D_X       количество  байтов  в  строке                  ********/
/***************************************************************************/
{  BYTE  j,*r;
   INT i,n_count=0,n=end-beg,den_x;
   dx-=1;
   den_x=3*(dx-(dx>>3));
   for (r=RAST+beg*D_X,i=0;i<=n;i++,r+=D_X){
      j=(BYTE)SumIntervalBits( r,1,dx ) ;
      if( j>=den_x )
	{  n_count++; }
   }

   return(n_count);        /* ... */
}  /*  */

static INT DiskrimM(BYTE *RAST,INT D_X,INT dx,INT dy)
/***************************************************************************/
/****     *RAST      указатель   на  масив                          ********/
/****      dx        количество  битов  в  строке                   ********/
/****	   dy        kоличество  строк                              ********/
/****      D_X       количество  байтов  в  строке                  ********/
/***************************************************************************/
{
   INT    n2,n4=dy>>2,meanBit=dx>>1; /* Oleg & Vova 09.03.94 */
   INT    i,j,k,up=0,down=0,cUp=0,cDown=0;
   INT    prev=0,byte=0;
   BYTE   *r;

/*  calculate  mean  of  hole  */
   for(r=RAST+D_X,i=0;i<n4;i++,r+=D_X){
      j = NumHorizInterval( r, D_X );
      if( j == 2 ){
	 for(k=0;k<dx;k++){
	    byte=k>>3;
	    byte=*(r+byte);
	    byte >>= ( 7- (k % 8) );
	    byte &= 0x1;
	    if( !byte && prev  && !down )  down = k;
	    if(  byte && !prev && down )   up   = k;
	    prev = byte;
	 }
   meanBit = ( up+down+(dx>>1) )/3;
	 /* for  no  wide  letters */
	 if( (up-down < 5) || (dx<dy) )  meanBit = ( up+down )/2;
	 break;
      }
   }
if( down==0 && up==0 )  return(2); /* м - hole is absent */

/*  calculate  heigth  of  hole  */
   r=RAST+D_X;
   byte = 0;
   prev = whiteMeanBitLeft(r,D_X,meanBit) +
	  whiteMeanBitRight(r,D_X,dx,meanBit);
   for(i=1;i<dy-1;i++,r+=D_X){
      j = whiteMeanBitLeft(r,D_X,meanBit) +
	  whiteMeanBitRight(r,D_X,dx,meanBit);
      if( (j == 0) && (i > n4+1) ){  break;  }
      byte += (prev-j);
      /* for  'ы' */
      if( (byte < 2) && (i > n4+2) ){
         break;
      }
      prev = j;
   }
   if( i > dy-2 )  i = 2*dy/3;
   n4 = i>>1;  n2 = 2*n4;
/*  calculate  symetry  of  hole  */
   down = up = byte = 0;
   r=RAST+D_X;
   prev = whiteMeanBitLeft(r,D_X,meanBit) +
          whiteMeanBitRight(r,D_X,dx,meanBit);
   for(i=1;i<=n2;i++,r+=D_X){
      j = whiteMeanBitLeft(r,D_X,meanBit) +
	  whiteMeanBitRight(r,D_X,dx,meanBit);
      if( i<=n4 ){  up   += j;  cUp++;    }
      else       {  down += j;  cDown++;  }
      /* too  wide  hole */
      if( (i>n4) && (j>dx/3) ){
	 if( (cUp==0) || (cDown==0) )  return(0);
	 if( up*cDown <= down*cUp )    return(4);  /* ы - too  wide  hole */
	 if( byte < 3 )                return(3);  /* ы - too  wide  hole */
      }
      byte += (prev-j);
      if( (prev-j > 3) && (i>n4) )  return(5);      /* ы - too  big  jump */
      if( (byte >= dx/4) && (i>n4) )  return( -6 ); /* м - too  big  angle  for  cursive */
      prev = j;
   }

   if( (cUp != cDown) && (cDown) ){  down *= cUp;  down /= cDown;  }
   if( down >= up )  return(5);  /* ы - wide  hole on  the  bottom */
   if( down < up )  return(-5); /* м - wide  hole on  the  top */
   if( !cDown )  return(6);  /* ы - hole is absent */

   return(0);
}  /* DiskrM */

static INT DiskrimM1(BYTE *RAST,INT D_X,INT dx,INT dy)
/***************************************************************************/
/****     *RAST      указатель   на  масив                          ********/
/****      dx        количество  битов  в  строке                   ********/
/****	   dy        kоличество  строк                              ********/
/****      D_X       количество  байтов  в  строке                  ********/
/***************************************************************************/
{
   INT    n2,n4=dy>>2,meanBit=dx>>1; /* Oleg & Vova 09.03.94 */
   INT    i,j,k,up=0,down=0,cUp=0,cDown=0;
   INT    prev=0,byte=0;
   BYTE   *r;

/*  calculate  mean  of  hole  */
   for(r=RAST+D_X,i=0;i<n4;i++,r+=D_X){
      j = NumHorizInterval( r, D_X );
      if( j == 2 ){
	 if( ( j = NumHorizInterval( r+D_X, D_X ) ) ==2 ){
	    r += D_X;
	 }
	 for(k=0;k<dx;k++){
	    byte=k>>3;
	    byte=*(r+byte);
	    byte >>= ( 7- (k % 8) );
	    byte &= 0x1;
	    if( !byte && prev  && !down )  down = k;
	    if(  byte && !prev && down )   up   = k;
	    prev = byte;
	 }
	 meanBit = ( up+down+(dx>>1) )/3;
	 /* for  no  wide  letters */
	 if( (up-down < 5) || (dx<dy) )  meanBit = ( up+down )/2;
	 break;
      }
   }

/*  calculate  heigth  of  hole  */
   r=RAST+D_X;
   byte = 0;
   prev = whiteMeanBitLeft(r,D_X,meanBit);
   for(i=1;i<dy-1;i++,r+=D_X){
      j = whiteMeanBitLeft(r,D_X,meanBit);
      if( (j == 0) && (i > n4+1) ){  break;  }
      byte += (prev-j);
      /* for  'ы' */
      if( (byte < 1) && (i > n4+2) ){
	 break;
      }
      prev = j;
   }
   if( i > dy-2 )  i = 2*dy/3;
   n4 = i>>1;  n2 = 2*n4;

/*  calculate  symetry  of  hole  */
   down = up = byte = 0;
   r=RAST+D_X;
   prev = whiteMeanBitLeft(r,D_X,meanBit);
   for(i=1;i<=n2;i++,r+=D_X){
      j = whiteMeanBitLeft(r,D_X,meanBit);
      if( i<=n4 ){  up   += j;  cUp++;    }
      else       {  down += j;  cDown++;  }
      /* too  wide  hole */
      if( (i>n4) && (j>dx/5) ){
	 if( (cUp==0) || (cDown==0) )  return(0);
	 if( up*cDown <= down*cUp )    return(4);  /* ы - too  wide  hole */
	 if( byte < 1 )                return(3);  /* ы - too  wide  hole */
      }
      byte += (prev-j);
      if( (prev-j > 3) && (i>n4) )  return(5);      /* ы - too  big  jump */
      if( (byte > 1+dx/8) && (i>n4) )  return( -6 ); /* м - too  big  angle  for  cursive */
      prev = j;
   }

   if( (cUp != cDown) && (cDown) ){  down *= cUp;  down /= cDown;  }
   if( down >= up )  return(5);  /* ы - wide  hole on  the  bottom */
   if( down < up )  return(-5); /* м - wide  hole on  the  top */
   if( !cDown )  return(6);  /* ы - hole is absent */

   return(0);
}  /* DiskrM1 */

static INT whiteMeanBitLeft(BYTE *RAST,INT D_X,INT meanBit)
/***************************************************************************/
/****     *RAST      указатель   на  масив  с  учетом  пропуска     ********/
/****			      первой  строчки                       ********/
/****      dx        количество  битов  в  строке                   ********/
/****      D_X       количество  байтов  в  строке                  ********/
/***************************************************************************/
{
   INT    meanByte, byte;
   INT    i,counter=0;

   for(i=meanBit;i>=0;i--){
      meanByte = i>>3;
      byte = *(RAST+meanByte);
      byte >>= ( 7- (i % 8) );
      byte &= 0x1;
      if(byte){
         meanByte = (i-1)>>3;
	 byte = *(RAST+meanByte);
	 byte >>= ( 7- ((i-1) % 8) );
	 byte &= 0x1;
	 if(byte)  break;
	 else{
	    meanByte = i>>3;
	    byte = *(RAST+D_X+meanByte);
	    byte >>= ( 7- (i % 8) );
	    byte &= 0x1;
            if(byte)  break;
	    else{
	       meanByte = i>>3;
	       byte = *(RAST-D_X+meanByte);
	       byte >>= ( 7- (i % 8) );
	       byte &= 0x1;
	       if(byte)  break;
	       else      counter++;
	    }
         }
      }
      else  counter++;
   }

   return( counter );
}  /* whiteMeanBitLeft */

static INT whiteMeanBitRight(BYTE *RAST,INT D_X,INT dx,INT meanBit)
/***************************************************************************/
/****     *RAST      указатель   на  масив  с  учетом  пропуска     ********/
/****			      первой  строчки                       ********/
/****      dx        количество  битов  в  строке                   ********/
/****      D_X       количество  байтов  в  строке                  ********/
/***************************************************************************/
{
   INT    meanByte, byte;
   INT    i,counter=0;

   for(i=meanBit+1;i<dx;i++){
      meanByte = i>>3;
      byte = *(RAST+meanByte);
      byte >>= ( 7- (i % 8) );
      byte &= 0x1;
      if(byte){
	 meanByte = (i+1)>>3;
	 byte = *(RAST+meanByte);
	 byte >>= ( 7- ((i+1) % 8) );
	 byte &= 0x1;
	 if(byte)  break;
	 else{
	    meanByte = i>>3;
	    byte = *(RAST+D_X+meanByte);
	    byte >>= ( 7- (i % 8) );
	    byte &= 0x1;
            if(byte)  break;
	    else{
	       meanByte = i>>3;
	       byte = *(RAST-D_X+meanByte);
	       byte >>= ( 7- (i % 8) );
	       byte &= 0x1;
	       if(byte)  break;
	       else      counter++;
	    }
         }
      }
      else  counter++;
   }

   return( counter );
}  /* whiteMeanBitRight */

INT LepikJurit( BYTE *R, INT D_X, INT dy)
{
  INT y2,y4,i;
  INT ug,ugg, bg;
  INT us/*,bs*/;   /* Oleg : Lepic ne jurit etoi peremennoi */
  INT uu;
  INT ret;
  BYTE *r;
  y2 = dy/2;
  y4 = dy/4;
  ug = bg = 0;
  for (i = 0, r = R+D_X*y4; i <y4;  i++ ,r+=D_X )
      {
        ret = LeftEdgeOfRightmostInt (r, D_X);
        if (ug <ret){  ug = ret; us =i;}
      }
 ugg = ug;
  for (         ;    i <y2;   i++, r+= D_X)
      {
        ret = LeftEdgeOfRightmostInt (r, D_X);
	if (bg <ret) { bg = ret; /* bs =i;*/}
      }
 uu = 0;
 for (i =us+1, r =R +D_X*(y4+i); i <y4+2; i++, r+=D_X)
  {
        ret = LeftEdgeOfRightmostInt (r, D_X);
        if ((ret <ug) &&(ug -ret<3)) { uu++; ug =ret;}
	 else if((uu >= 2)) break;
                else uu=0;
  }


 return ((ugg < bg)||(uu>=2)) ? 1 : 0;
}

/* 1 строка пропущена сверху, 1 - снизу */
INT up_down_hist_M(BYTE *rastr,INT D_X, INT Dx,INT dy)
{
INT i,j,d,h=dy>>1,s,t,n;
BYTE *r;

Dx =  bytlen(Dx);
for(s=j=0,i=0,r=rastr+i*D_X;i<h;j++,i++,r+=D_X)
	{
	n = NumHorizInterval( r, Dx ) ;
	s += (n==2);
	if( s>2 )               break;
	if( j>3 && s==0 )       break;
	}
if( s<2 )			return(0);

for(t=d=j=0,i=dy-1,r=rastr+i*D_X; i>=h;i--,j++,r-=D_X)
	{
	n = NumHorizInterval( r, Dx ) ;
	t += (n==3);
	d += (n==2);
	if( d>2 )		break;
	if( t>2 )   		break;
	if( j>3 && t==0 )	break;
	}

if( t<2 )			return(0);

if( s>3 && t>3 )		return( 8 );
return(4);
}

/*  для 'ш': ноги на одинаковом расстоянии? Да: <0; нет: >0; неясно: 0 */
static INT DiskrSymSh( BYTE *RASTER, INT Wx, BYTE NWIDTH, BYTE NLENGTH)
{
  INT i,old,l,k,d;
  BYTE c,w,minw=255,maxw=0;

  FOOT_A(RASTER,Wx,NWIDTH,NLENGTH);       /* проекция */

d=(NLENGTH+1)>>1;
for(i=0;i<NWIDTH;i++)
	BUFFER[i] = (BUFFER[i]>=d); /* бинаризация */

for(old=l=k=i=0;i<=NWIDTH;i++)
	{
    c = (i<NWIDTH) ? BUFFER[i] : 0;
	if( old^c )
		{
        if( c )
			l=i;			/* черная  : начало ноги */
		else
            {               /* белая   : конец ноги  */
            w=i-l;
            if (w>maxw)  maxw=w;
            if (w<minw)  minw=w;
            LOCAL_W[k]=w;    /* ширина ноги   */
            LOCAL[k]=(l+i);  /* центр+1/2 с точностью до 1/2 пиксела */
            k++;
			}
		}
	old=c;
	}

  if ( k != 3 || maxw-minw>1 )  return(0);    //странная буква
  i=LOCAL[2]+LOCAL[0]-(LOCAL[1]<<1);          //асимметрия
  if (i==0)  return (-2);
  if (i<0) i=-i;
  if( i<3 && NWIDTH>22 )  i=1;  //Oleg:02-13-96: too small for wide image
  i=(i<<6)/(32+NWIDTH);
  if (i==1) i=0;
  return(i);
}
