#include "types.h" /* Type definitions */
#include "global_refs.h" /* Globals that we must see */
#include "pdf417.h"
#include "Codewrd0.h"
#include "Codewrd3.h"
#include "Codewrd6.h"
#include "subchar.h"
#include "errorlev.h"
extern unsigned char adex_value;
#define ERRBUFLEN 42
#define PADDING_WORD 900
#define MODE_TEXT_ALPHA 1
#define MODE_TEXT_LOWER 2
#define MODE_TEXT_MIXED 4
#define MODE_TEXT_PUNCT 8
#define MODE_NUMERIC 16
#define MODE_BYTE 32
#define MODE_BS 64
//const unsigned char *errbptr=(char *)&text_buff;
//const PDFBUFF *pdfbuff=(PDFBUFF *)(((char*)&text_buff)+ERRBUFFLEN);
const int errbptr=(int)&text_buff;
const int pdfbufp=ERRBUFLEN+4+(int)&text_buff;
/*FIXME 4 bytes*/
#define errbuff ((unsigned char *)errbptr)
#define pdfbuff ((PDFBUFF *)pdfbufp)
void mydeb_putc(unsigned char c)
{
putchar((((c)&0xf0)>>4)+'0');
putchar(((c)&0xf)+'0');
}
void mydeb_puti(unsigned int i)
{
mydeb_putc(i>>8);
mydeb_putc(i&0xff);
}
void crlf(){
putchar('\n');
putchar('\r');
}
void print_stack()
{
unsigned char *ptrke;
unsigned char *tmp;
tmp=&adex_value;
ptrke=tmp;
tmp+=0x1f;
crlf();
for(;ptrke<tmp;ptrke++)
{
mydeb_putc(*ptrke);
}
crlf();
}
#define print_sp()
//#define print_sp() mydeb_puti(_asm("tsx\n pshh\n pula"));
void mydebug(char*ptr,unsigned char len)
{
for(;len>0;len--)
{
mydeb_putc(*ptr);
ptr++;
}
crlf();
}
/*-------------------------------------------------------*/
#define tmpvaruc0 (pdfbuff->tmp.uc[0])
#define tmpvaruc1 (pdfbuff->tmp.uc[1])
#define cols (pdfbuff->Cols)
#define errlev (pdfbuff->Errlev)
#define rows (pdfbuff->Rows)
#define line (pdfbuff->Line)
#define datalenke (pdfbuff->Datalen)
#define mrfifo_data (pdfbuff->Data)
#define mrfifo_len (pdfbuff->Len)
#define mrfifo_oldmode (pdfbuff->Oldmode)
#define mrfifo_datalen (pdfbuff->Fifolen)
#define mrfifo_round (pdfbuff->Round)
void mrfifo_init();/* does init for cv and output (err) as well */
void mrfifo_fill();
void mrfifo_shift(unsigned char count);
unsigned char mrfifo_newmode();
#define cv_text_data (pdfbuff->Text_data)
#define CV_NODATA 31
char cv_text_eat();
void cv_text_done();
void cv_text_start(unsigned char newmode);
char cv_num_worth();
char cv_num_eat();
void cv_num_start(unsigned char newmode);
/*void cv_num_done(); optimized out*/
char cv_byte_eat();
void cv_byte_start(unsigned char newmode);
/*void cv_byte_done(); optimized out */
char cv_bs_eat();
void cv_bs_start(unsigned char newmode);
/* void cv_bs_done(); optimized out */
#define output_prlen (pdfbuff->Prlen)
void output_add(int codeword);
void output_p_ercompute(int codeword);
void output_p_print(int codeword);
void math_num_prepare(char len);
int math_div_num(char start,char len);
int math_div_256(char len);
void math_num_print(char len);
#define panic(a) putchar('*');putchar(a);
/*-------------------------------------------------------*/
void mrfifo_loop()
{
unsigned char newmode;
while((mrfifo_datalen>0) || (mrfifo_len > 0 ))
{
mrfifo_fill();
newmode=mrfifo_newmode();
if(newmode != mrfifo_oldmode)
{
if((mrfifo_oldmode &0x0f)&&(!(newmode&0x0f)))
/* it was text */
{
cv_text_done();
}
switch(newmode)
{
case MODE_TEXT_ALPHA:
case MODE_TEXT_LOWER:
case MODE_TEXT_MIXED:
case MODE_TEXT_PUNCT:
cv_text_start(newmode);
break;
case MODE_BYTE:
cv_byte_start(newmode);
break;
case MODE_NUMERIC:
cv_num_start(newmode);
break;
case MODE_BS:
cv_bs_start(newmode);
break;
default:
panic('A');
}
}
switch(newmode){
case MODE_TEXT_ALPHA:
case MODE_TEXT_LOWER:
case MODE_TEXT_MIXED:
case MODE_TEXT_PUNCT:
mrfifo_shift(cv_text_eat());
break;
case MODE_BYTE:
mrfifo_shift(cv_byte_eat());
break;
case MODE_NUMERIC:
mrfifo_shift(cv_num_eat());
break;
case MODE_BS:
mrfifo_shift(cv_bs_eat());
break;
default:
panic('B');
}
}
if(mrfifo_oldmode &0x0f)
{
cv_text_done();
}
}
void mrfifo_shift(unsigned char count)
{
unsigned char i;
if(count>mrfifo_len)
{
panic('D');
}
for(i=0;i<mrfifo_len-count;i++)
{
mrfifo_data[i]=mrfifo_data[i+count];
}
mrfifo_len-=count;
mrfifo_fill();
}
void mrfifo_fill()
{
while((mrfifo_len < (MRFIFO_DATA_LEN-1)) && (mrfifo_datalen > 0))
{
mrfifo_data[mrfifo_len]=getchar('a');
//putchar('f');
//mydeb_putc(mrfifo_data[mrfifo_len]);
mrfifo_len++;
mrfifo_datalen--;
}
}
unsigned char mrfifo_p_onemode(unsigned char c)
{
unsigned char mode;
unsigned char i;
print_sp();
mode=0;
if(('0' <= c ) && ( c <= '9'))
{
mode |= cv_num_worth();
}
if((('A' <= c) && ( c <= 'Z')) || c == ' ')
{
mode|=MODE_TEXT_ALPHA;
}
if((('a' <= c) && ( c <= 'z')) || c == ' ')
{
mode|=MODE_TEXT_LOWER;
}
for(i=0;i<25;i++)
{
if(c==mixtab[i]) {
mode |= MODE_TEXT_MIXED;
break;
}
}
for(i=0;i<29;i++)
{
if(c==puntab[i]) {
mode |= MODE_TEXT_PUNCT;
break;
}
}
if(0==mode)
{
mode = MODE_BYTE;
}
return(mode);
#undef mode
#undef i
}
unsigned char mrfifo_newmode()
{
unsigned char i;
unsigned char thismode;
thismode=mrfifo_p_onemode(mrfifo_data[0]);
if(thismode&MODE_NUMERIC)
{
return MODE_NUMERIC;
}
#define nextmode mrfifo_p_onemode(mrfifo_data[1])
if((mrfifo_oldmode&0xf)&&(nextmode&0xf)&&(thismode==MODE_BYTE))
{
return MODE_BS;
}
if(thismode == MODE_BYTE)
{
return MODE_BYTE;
}
if(thismode&mrfifo_oldmode)
{
/* We could further optimize it, with nextmode, but won't */
return mrfifo_oldmode;
}
if(thismode&nextmode)
{
unsigned char mode=thismode&nextmode;
/* It could be optimized by oldmode, and the precedencies*/
if(mode&MODE_TEXT_ALPHA)
{
return MODE_TEXT_ALPHA;
}
if(mode&MODE_TEXT_LOWER)
{
return MODE_TEXT_LOWER;
}
if(mode&MODE_TEXT_MIXED)
{
return MODE_TEXT_MIXED;
}
if(mode&MODE_TEXT_PUNCT)
{
return MODE_TEXT_PUNCT;
}
panic('E');
}
for(i=0;thismode;i++)
{
thismode=thismode>>1;
}
thismode=1;
thismode=thismode<<(i-1);
return thismode;
}
void cv_text_p_eat(unsigned char c)
{
if(cv_text_data != CV_NODATA)
{
output_add(cv_text_data*30+c);
cv_text_data = CV_NODATA;
} else {
cv_text_data = c;
}
}
char cv_text_eat()
{
unsigned char i;
switch(mrfifo_oldmode)
{
case MODE_TEXT_ALPHA:
mrfifo_data[0]=mrfifo_data[0]-'A';
break;
case MODE_TEXT_LOWER:
mrfifo_data[0]-='a';
break;
case MODE_TEXT_MIXED:
for(i=0;i<25;i++)
{
if(mixtab[i]==mrfifo_data[0])
{
mrfifo_data[0]=i;
break;
}
}
break;
case MODE_TEXT_PUNCT:
for(i=0;i<29;i++)
{
if(puntab[i]==mrfifo_data[0])
{
mrfifo_data[0]=i;
break;
}
}
break;
default:
panic('F');
}
cv_text_p_eat(mrfifo_data[0]);
return 1;
}
void cv_text_done()
{
//putchar('D');
if(cv_text_data != CV_NODATA)
{
output_add(cv_text_data*30+29);
if(mrfifo_oldmode == MODE_TEXT_PUNCT)
{
mrfifo_oldmode = MODE_TEXT_ALPHA;
}
/* it would be PS, but if byteshift follows, it is
ignored, else it is not significant*/
}
//putchar('d');
}
void cv_text_start(unsigned char newmode)
{
unsigned char i,j;
if(0 == (mrfifo_oldmode & 0xf )) /* it was not text mode */
{
output_add(900);
} else {
unsigned char nm;
i=0xff;
j=0xff;
nm=newmode;
for(;newmode;newmode = newmode >> 1)
{
i++;
}
if(i>3)
{
panic('G');
}
newmode=mrfifo_oldmode;
for(;newmode;newmode = newmode >>1)
{
j++;
}
if(j>3)
{
panic('H');
}
newmode=nm;
nm=i*2+j*8;
if(txt_jumptab[nm])
{
cv_text_p_eat(txt_jumptab[nm]);
if(txt_jumptab[nm+1])
{
cv_text_p_eat(txt_jumptab[nm+1]);
}
} else {
panic('I');
}
}
mrfifo_oldmode=newmode;
}
char cv_num_worth()
{
char i;
for(i=0;i<mrfifo_len;i++)
{
if(('0' > mrfifo_data[i]) || (mrfifo_data[i] > '9'))
{
break;
}
}
if(i>5) {
return MODE_NUMERIC;
}
return 0;
}
char cv_num_eat()
{
char i;
for(i=0;i<mrfifo_len;i++)
{
if(('0' > mrfifo_data[i]) || (mrfifo_data[i] > '9'))
{
break;
}
}
math_num_print(i);
return(i);
}
void cv_num_start(unsigned char newmode)
{
output_add(902);
mrfifo_oldmode=newmode;
}
char cv_byte_p_num()
{
char i;
for(i=0;(i<mrfifo_len&&i<6);i++)
{
if(!(MODE_BYTE&&mrfifo_p_onemode(mrfifo_data[i])))
{
break;
}
}
return i;
}
void cv_byte_emit(char len)
{
for(;len>1;len--)
{
int sok;/*FIXME just for debug, can be eliminated*/
sok=math_div_256(len);
output_add(sok);
// output_add(math_div_256(len));
mrfifo_shift(1);
}
mrfifo_shift(1);
}
char cv_byte_eat()
{
if(cv_byte_p_num()>=6)
{
output_add(924);
}
while(cv_byte_p_num()>=6)
{
cv_byte_emit(6);
}
output_add(901);
cv_byte_emit(cv_byte_p_num());
return(0);
}
void cv_byte_start(unsigned char newmode)
{
/*FIXME*/
mrfifo_oldmode=newmode;
}
int math_div_256(char len)
{
/*FIXME optimize out i*/
unsigned int modulo;
char i;
modulo=*mrfifo_data;
mrfifo_data[0]=0;
for(i=2;i<len*2;i++)
{
modulo<<=4;/*shift mod*/
if(!(i%2))
{
/*paros*/
modulo+=((mrfifo_data[i/2])&0xf0)>>4;/*shift data*/
/*div data -> data high*/
mrfifo_data[i/2]=((char)(((modulo/900)<<4)&0xf0)|
((mrfifo_data[i/2])&0x0f));
} else {
/*paratlan*/
modulo+=(mrfifo_data[i/2])&0x0f;/*shift data*/
/*div data -> data high*/
mrfifo_data[i/2]=(((char)(modulo/900))&0x0f)|
(0xf0&(mrfifo_data[i/2]));
}
modulo=modulo%900; /* mod mo*/
}
return modulo;
}
void math_num_print(char len)
{
char i;
signed char start=0;
math_num_prepare(len);
while(1)
{
*((int*)(mrfifo_data+start))=math_div_num(start,len);
start+=2;
len -=2;
for(i=0;i<len;i++)
{
if(mrfifo_data[i+start])
{
break;
}
}
if(i>=len)
{
break;
}
}
start-=2;
for(;start>=0;start-=2)
{
output_add(*(int*)(mrfifo_data+start));
}
}
void math_num_prepare(char len)
{
char i;
for(i=0;i<len;i++)
{
mrfifo_data[i]-='0';
}
mrfifo_data[0]+=10;
}
int math_div_num(char start,char len)
{
unsigned int modulo;
char i;
modulo=(int)(mrfifo_data[start]);
mrfifo_data[start]=0;
for(i=1;i<len;i++)
{
modulo*=10;
modulo+=mrfifo_data[i+start];
mrfifo_data[i+start]=((char)(modulo/900));
modulo=modulo%900;
}
return modulo;
}
char cv_bs_eat()
{
//putchar('y');
output_add(mrfifo_data[0]);
return 1;
}
void cv_bs_start(unsigned char newmode)
{
//putchar('z');
output_add(913);
return;
}
void output_add(int codeword)
{
//putchar('o');
if(2==mrfifo_round)
{
//putchar('O');
output_p_errcompute(codeword);
output_p_print(codeword);
}
output_prlen++;
}
void err_init()
{
char i;
for(i=0;i<ERRBUFLEN;i++)
{
errbuff[i]=0;
}
}
unsigned int readerr(unsigned char k)
{
return (((k)%2)?
((*((unsigned int*)(errbuff+((k)*3/2))))&0x0fff)
:
((*((unsigned int*)(errbuff+((k)*3/2))))>>4));
}
void writerr(unsigned char k,unsigned int i)
{
unsigned char *n=errbuff+k*3/2;
if((k)%2)
{
*(n+1)=i&0xff;
*n=(i>>8)|((*n)&0xf0);
} else {
*n=i>>4;
*(n+1)=((i&0xf)<<4)|
((*(n+1))&0x0f);
}
}
unsigned long int onehalf_mul(unsigned int t1,unsigned char i)
{
unsigned long int t2;
unsigned int t3;
unsigned char aj[2];
*((int *)aj)=levelx[errlev][i];
/* (px+q)*(rx+t) = prx^2+(qr+tp)x+tq; and pr is char */
/* t1 = px +q , a[j] = rx +t
* p=t1>>8, q=t1&0x0f
* r=aj[0], t=aj[1]
*/
/*pr*/
//!!t2=p*r, ok
t2=(t1>>8)*aj[0];
//!!t2=p*r*x
t2<<=8;
/*qr +tp*/
//!!t3=q*r
t3=(t1&0x0ff)*aj[0];
//mydeb_puti(t3);
//mydeb_puti(t2);
/*
* t2=t2+t3
* t2=p*r*x+q*r
*/
t2+=t3;
// /* +tp*/
/*
* t3=p*t
*/
t3=(t1>>8)*aj[1];
//mydeb_puti(t3);
//mydeb_puti(t2);
/*
* t2=t2+t3
* t2=p*r*x+q*r+p*t
*/
t2+=t3;
/*
* t2=t2*x
* t2=p*r*x^2+(q*r+p*t)*x
*/
t2<<=8;
// /* tq */
/*
* t3=q*t
*/
t3=(t1&0x0ff)*aj[1];
//mydeb_puti(t3);
/*
* t2=t2+t3
* t2=p*r*x^2+(q*r+p*t)*x+q*t
*/
t2+=t3;
//mydeb_puti(t2);
t2%=929;
return t2;
}
#define KA (2<<(errlev))
void output_p_errcompute(int codeword)
{
unsigned int t1;
unsigned char aj[2];
unsigned long int t2;
unsigned char *t2c=((unsigned char *)&t2);
unsigned int t3;
signed char i; //FIXME if errlev<=5
t1=(codeword+readerr(KA-1))%929;
//putchar('e');
//mydeb_puti(codeword);
//mydeb_puti(t1);
//mydeb_puti(readerr(KA-1));
//crlf();
for(i=KA-1;i>0;i--)
{
t2=onehalf_mul(t1,i);
//mydeb_puti(t2);
t3=929-t2;
writerr(i,(readerr(i-1)+t3)%929);
//putchar('E');
//mydeb_puti(t1);
//mydeb_puti(t2);
//mydeb_puti(t3);
//mydeb_puti(levelx[errlev][i]);
//mydebug(errbuff,24);
}
t2=onehalf_mul(t1,0);
t3=929-t2;
writerr(0,t3%929);
//putchar('F');
//mydeb_puti(t2);
//mydeb_puti(t3);
//mydebug(errbuff,24);
}
void output_p_print(int codeword)
{
if(0==((output_prlen % cols)))
{
output_newline();
}
print_codeword(codeword);
}
void error_print()
{
signed char i;
for(i=KA-1;i>=0;i--)
{
putchar('e');
if(readerr(i))
{
output_p_print(929-readerr(i));
} else {
output_p_print(0);
}
}
}
void mrfifo_done()
{
/* pad chars */
while(output_prlen<(rows*cols-(2<<errlev)))
{
output_add(PADDING_WORD);
}
/* error chars */
error_print();
output_newline();
}
void mrfifo_init()
{
unsigned char i;
for(i=0;i<MRFIFO_DATA_LEN;i++)
{
mrfifo_data[i]=0;
}
mrfifo_len=0;
mrfifo_oldmode=MODE_TEXT_ALPHA;
mrfifo_datalen=0;
cv_text_data=CV_NODATA;
output_prlen=1;
}
void output_start()
{
line=0;
bc_init_shifter();
print_codeword(STARTW);
print_codeword(0);
rows=((output_prlen+(2<<errlev)+cols/*would be (cols - 1) but + 1 for the length word */)/cols);
if(rows<3)
{
rows=3;
}
output_add(rows*cols-(2<<errlev));
}
void output_newline()
{
print_codeword(right_side());
print_stopword();
bc_print_graph();
crlf();
line++;
if(line < rows)
{
bc_init_shifter();
print_codeword(STARTW);
print_codeword(left_side());
}
}
//void output_end()
//{
// output_prlen,cols,rows,line
//
// /*FIXME print the error code */
//
//}
/*-------------------------------------------------------*/
extern const unsigned char bc_itf_font[];
void mydebug(char*ptr,unsigned char len);
extern const unsigned char bc_offsets[];
void bc_pdf417()
{
unsigned char ptrke;
crlf();
crlf();
crlf();
//putchar('A');
err_init();
mydeb_puti(_asm("tsx\n pshh\n pula"));
for(ptrke=1;ptrke<0x20;ptrke++)
{
*((&adex_value)+ptrke)=0xdd;
};
print_stack();
line_spacing=0;
bc.height/=8;
mrfifo_init();
cols = getchar('b');
errlev = getchar('c');
datalenke=0;
datalenke = getchar('d');
datalenke =datalenke << 8;
datalenke += (signed int)((unsigned char)getchar('e'));
if (datalenke == 0) { return ; } //0 length is not allowed
if (errlev>4) { errlev=4 ; } //allowed errorlevel is 0...4
if (cols < 5) { cols=5 ; } //0 width is not allowed
cols -= 4 ;
if (cols > MAXCOL ) { cols=MAXCOL ; }
print_mode.byte = 0; //any magnification off
//proba();
mrfifo_round=1;
mrfifo_datalen=datalenke;
mrfifo_loop();
mrfifo_round=2;
output_start();
mrfifo_init();
mrfifo_datalen=datalenke;
mrfifo_loop();
mrfifo_done();
//proba();
bc.height*=8;
print_stack();
}
void print_codeword(codeword)
{
unsigned char n;
unsigned int nn;
putchar('P');
mydeb_puti(codeword);
switch (line % 3)
{
case 0: codeword=codew0[codeword];
break;
case 1: codeword=codew3[codeword];
break;
case 2: codeword=codew6[codeword];
break;
}
nn = 0x8000 ;
for ( n = 0 ; n < 16 ; n ++ )
{
if (codeword&nn) bc_shift_bit_1(); else bc_shift_bit_0();
nn = nn >> 1;
}
bc_shift_bit_0();
}
void print_stopword()
{
print_codeword(STOPW);
bc_shift_bit_1();
}
unsigned int left_side()
{
//putchar('L');
//mydeb_putc(line);
//mydeb_putc(rows);
//mydeb_putc(cols);
//mydeb_putc(errlev);
switch (line % 3)
{
case 0: return ((10*line) + rows/3);
case 1: return ((10*line) + (errlev*3) + (rows%3));
case 2: return (60 + cols);
}
}
unsigned int right_side()
{
switch (line % 3)
{
case 0: return ((10*line) + cols);
case 1: return ((10*line) + (rows/3));
case 2: return (60 + (errlev*3) + (rows%3));
}
}
unsigned char proba()
{
line=0;
//getchar('E');
bc_init_shifter();
//getchar('D');
print_codeword(STARTW);
print_codeword(left_side());
print_codeword(453);
print_codeword(841);
print_codeword(63);
print_codeword(753);
print_codeword(897);
print_codeword(88);
print_codeword(right_side());
print_stopword();
//getchar('F');
bc_print_graph();
//getchar('G');
}