
#include <stdlib.h>
#include <dos.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>


int FIRST_PAGE = 1;
int LAST_PAGE = 999;
int FIRST_INPUT    = 1;
int LAST_INPUT     = 999;

char PRINT_NOKEYS;
char PRINT_TITLES;
char PRINT_2COL;
char UNDERLINE_MODE;
char PRINT_QUALITY = 1;
char PRINT_COMPRESS;
char PRINT_REDUCE;
char PRINT_SQUIZE;

char BOOKLET;
char BOOKLET_SKIP;

char CODES_RESET[MAXPRINTSIZE]        = { 2, 27, 64, 0, 0 };
char CODES_UNDER_ON[MAXPRINTSIZE]     = { 3, 27, 45, 1, 0 };
char CODES_UNDER_OFF[MAXPRINTSIZE]    = { 4, 27, 45, 0, 0 };
char CODES_COMPRESS_ON[MAXPRINTSIZE]  = { 1, 15,  0, 0, 0 };
char CODES_COMPRESS_OFF[MAXPRINTSIZE] = { 1, 18,  0, 0, 0  };
char CODES_DRAFT[MAXPRINTSIZE]        = { 3, 27, 73, 1, 0 };
char CODES_LETTER[MAXPRINTSIZE]       = { 3, 27, 73, 2, 0 };
char CODES_REDUCE_ON[MAXPRINTSIZE]    = { 2, 27, 48, 0, 0 };
char CODES_REDUCE_OFF[MAXPRINTSIZE]   = { 2, 27, 50, 0, 0 };
char CODES_SQUIZE_ON[MAXPRINTSIZE]    = { 2, 27, 77, 0, 0 };
char CODES_SQUIZE_OFF[MAXPRINTSIZE]   = { 2, 27, 80, 0, 0 };



void set_PRINTER(char *fdest)
{
 if(stricmp(fdest, "PRN")  == 0) goto to_printer;
 if(stricmp(fdest, "LPT1") == 0) goto to_printer;
 if(stricmp(fdest, "LPT2") == 0) goto to_printer;
 TO_PRINTER = 0;
 return;

to_printer:
 TO_PRINTER = 1;
 return;
}

void send_codes(char *SERIE)
{
 int i;
 int j;

 i = SERIE[0];
 j = 1;
 while(i)
 {
   fputc(SERIE[j++], PP);
   i--;
 }
}

void underline_on()
{
 send_codes(CODES_UNDER_ON);
 UNDERLINE_MODE = 4;
}

void underline_off()
{
 if(UNDERLINE_MODE)
 {
  if(TO_PRINTER) send_codes(CODES_UNDER_OFF);
  UNDERLINE_MODE = 0;
 }
}


void configure_printer()
{
 if(TO_PRINTER)
 {
  send_codes(CODES_RESET);
  if(PRINT_QUALITY) send_codes(CODES_LETTER);
	       else send_codes(CODES_DRAFT);
  if(PRINT_COMPRESS) send_codes(CODES_COMPRESS_ON);
		else send_codes(CODES_COMPRESS_OFF);
  if(PRINT_REDUCE) send_codes(CODES_REDUCE_ON);
	      else send_codes(CODES_REDUCE_OFF);
  if(PRINT_SQUIZE) send_codes(CODES_SQUIZE_ON);
	      else send_codes(CODES_SQUIZE_OFF);
  underline_off();
 }
 return;
}



int AskPrint2Col(char *text)
{
 int col, colr, lin, linb;
 int ch;
 int line;
 char first[6];
 char last[6];
 int ml, mc;

 if(!printer_ready() ) return(0);

 itoa(FIRST_INPUT, (char *) first, 10);
 itoa(LAST_INPUT, (char *) last, 10);
 FIRST_PAGE = FIRST_INPUT;
 LAST_PAGE  = LAST_INPUT;
 line = 0;

 DIALOG_BAR = 1;
 DIALOG_BARCOL = 3;
 DIALOG_BACK = 7;
 DIALOG_KEYS = 0;

 col =  20;
 colr = 60;
 lin =  10;
 linb = 19;

 mhide();
 winbacksave(col, lin, colr, linb);
 wincolor(7, 4, 0);
 winboard(col, lin, colr, linb, 7);
 writeonxy(22 << 3, (10 << 4) + 7, "Printing");

 winwritef18(2, 3, "DOCUMENT: %-s", text);

 go_key(  32, 7);
 stop_key(32, 4);

 winwrite18(2, 5, "First page:");
 winwrite18(2, 7, "Last page:");
 getcadre(17, 5, 6); putkey16(WL + 23, WU + 6, 13);
 getcadre(17, 7, 6); putkey16(WL + 23, WU + 8, 14);

getloop:
 wintextcol(15, 0);
 winwritef18(17, 5, "%-4s", first);
 winwritef18(17, 7, "%-4s", last);
 winlocate(17, 5 + line);
 if(!line) ch = getsg(first, 4);
   else    ch = getsg(last, 4);

parse:
 mhide();
 switch(ch)
 {
   case KEY_UP:
   case KEY_DOWN: line = 2 - line & 2;
		  goto getloop;

   case -3:  if(wininside())
	      {
	       if(test16(13)) { *first = '1'; goto getloop;}
	       if(test16(14)) { *last  = '1'; goto getloop;}
	       if(test_go())   { ch = ENTER; goto parse;}
	       if(test_stop()) { ch = ESCAPE; goto parse;}
	       ml = (my >> 4) - WU;
	       mc = (mx >> 3) - WL;
	       if(mc >= 17)
		{
		 if((ml == 5) && (mc < 21))  { line = 0; goto getloop; }
		 if((ml == 7) && (mc < 21))  { line = 2; goto getloop; }
		}
	       }
	      break;

   case ENTER:  FIRST_INPUT = max(atoi(first), 1);
		LAST_INPUT  = min(atoi(last), 999);
		FIRST_PAGE = FIRST_INPUT;
		LAST_PAGE  = LAST_INPUT;
   case ESCAPE: goto exit;
   default:  break;

 }
goto getloop;

exit:
 return(ch == 13);
}


void print_1col(char *asktext, char *title, char *fdest, char huge *textadr, char huge *lastadr)
{
 set_PRINTER(fdest);
 if(!AskPrint2Col(asktext)) return;

 if(FIRST_PAGE > 1)
  {
   textadr = SKIP_Text(textadr, lastadr, FIRST_PAGE);
   if(!textadr) return;
   PAGE_NUMBER = FIRST_PAGE;
  }
 else
  PAGE_NUMBER = 1;

 ligne_de_page = 0;        /* lines on this page so far */

 make_file_print(title);

 PP = fopen(fdest, "w");

 configure_printer();

 while(textadr < lastadr)
 {
  if(PAGE_NUMBER > LAST_PAGE) goto bye;
  if(*textadr == 0x1a) goto bye;
  if(*textadr == 4)
   {
    if(TO_PRINTER) underline_on();
    textadr++;
   }

  if(Header(1) == 27) goto bye;
  if(!PRINT_NOKEYS || *textadr != '#')
    if(print_a_line((char *) textadr) == 27) goto bye;

  underline_off();
  textadr = hugepint(textadr , strlen((char *) textadr) + 1);
 }

bye:
 fclose(PP);
}


/* SKIP */

int SKIP_Header(int PAGE)
{

 if(ligne_de_page > PRINT_LINES)  ligne_de_page = 0;
 if(ligne_de_page == 0)
  {
   if(PRINT_HEADER) ligne_de_page = HEADER_BOTTOM + 1;
   PAGE_NUMBER++;
   if(PAGE_NUMBER == PAGE) return(13);
  }
 return(0);
}


int SKIP_Line(char *oneline)
{
 int index;
 int length;
 int ctr;
 char c;

 length = strlen(oneline);
 ctr = 0;
 for(index = 0; index < length; index++)
  {
   c = oneline[index];
   if(c == 12)
    {
     ligne_de_page = PRINT_LINES;
     goto bye;
    }

   if(c == 21) goto nextchar;
   if((c == '\n') || (ctr == PRINT_COLUMNS))
    {
     ligne_de_page++; ctr = 0;
    }
nextchar:
   ctr++;
 }

bye:
 return(13);
}


char huge *SKIP_Text(char huge *textadr, char huge *lastadr, int PAGE)
{
 ligne_de_page = 0;

loop:
 while(textadr < lastadr)
 {
  if(*textadr == 0x1a) goto bye;
  if(SKIP_Header(PAGE) == 13) goto ok;

  if(*textadr == 4) textadr++;
  if(!PRINT_NOKEYS || *textadr != '#')
    if(SKIP_Line((char *) textadr) == 27) goto exit;
  textadr = hugepint(textadr , strlen((char *) textadr) + 1);
  ligne_de_page++;
 }

bye:
 if(ligne_de_page) goto ok;
exit:
 return(0L);

ok:
 return(textadr);
}


/* Passe la page gauche */
/* Il faut d‚duire les lignes de marge d'en-tˆte du d‚compte */

char huge *SKIP_Page(char huge *textadr, char huge *lastadr)
{
 int ctr;
 int top;
 int somelines;

 if(PRINT_HEADER) top = HEADER_BOTTOM;
 else top = 0;

 ctr = PRINT_LINES - top;
 somelines = 0;

loop:
 while((textadr < lastadr) && ctr--)
 {
  if(*textadr == 0x1a) goto bye;
  if(*textadr == 4) textadr++;
  if(!PRINT_NOKEYS || *textadr != '#')
    if(SKIP_Line((char *) textadr) == 27) goto exit;
  textadr = hugepint(textadr , strlen((char *) textadr) + 1);
  somelines++;
 }

bye:
 if(somelines) goto ok;
exit:
 return(0L);

ok:  return(textadr);

}



int print_half_line(char *oneline)
{
 int index;
 int size;
 char c;

 size = PRINT_LEFT;
 while(size) { size--; printchar(' '); }

 size = min(strlen(oneline), PRINT_COLUMNS);
 for(index = 0; index < size; index++)
  {
   c = oneline[index];
   if(c == 12)
    {
     ligne_de_page = PRINT_LINES;
     goto bye;
    }

   if(c == '\n') goto bye;
   printchar(c);
nextchar:;
  }

bye:
 return(index);
}


int PrintSemiLine(char *adr)
{
 int ret;
 int souligne;

 ret      = -1;
 souligne = 0;

 if(*adr == 0x1a) goto bye;
 if(*adr == 4)
  {
   if(PRINT_TITLES) { ret = 0; goto bye;}
   if(TO_PRINTER) underline_on();
   adr++;
   souligne = 1;
  }

 if(PRINT_NOKEYS && (*adr == '#'))
  ret = 0;
 else
  ret = print_half_line(adr);

bye:
 underline_off();
 return(ret + souligne);
}


void print_2col(char *asktext, char *title, char *fdest, char huge *textadr, char huge *lastadr)
{
 int ctr;
 int length;
 int i;
 char huge *textadr2;
 char huge *leftadr;

 set_PRINTER(fdest);
 if(!AskPrint2Col(asktext)) return;

 PAGE_NUMBER  = FIRST_PAGE;
 PAGE_PRINTED = FIRST_PAGE;

 if(FIRST_PAGE > 1)
  {
   textadr = SKIP_Text(textadr, lastadr, FIRST_PAGE);
   if(!textadr) return;
  }

 leftadr  = textadr;
 textadr2 = SKIP_Page(leftadr, lastadr);
 if(!textadr2)
  {
   print_1col(asktext, title, fdest, textadr, lastadr);
   return;
  }

 ligne_de_page = 0;        /* lines on this page so far */

 make_file_print(title);
 PP = fopen(fdest, "w");
 configure_printer();

 while(leftadr < lastadr)
 {
  if(PAGE_NUMBER > LAST_PAGE) goto bye;
  i = Header(2);
  if(i == 27) goto bye;
  if(i == 13)
  {
   if(!textadr2) goto bye;
   leftadr  = textadr2;
   textadr2 = SKIP_Page(leftadr, lastadr);
  }

  length  = strlen((char *) leftadr);
  ctr     = PrintSemiLine((char *) leftadr);
  if(ctr == -1) goto bye;          /* EOF found */
  while(ctr++ < (PRINT_COLUMNS + PRINT_LEFT)) printchar(' ');
  leftadr = hugepint(leftadr, length + 1);

  if(textadr2)
  {
   length   = strlen((char *) textadr2);
   ctr      = PrintSemiLine((char *) textadr2);
   textadr2 = hugepint(textadr2, length + 1);
  }

  nextline();
  ligne_de_page++;
 }

bye:
 fclose(PP);
}


/*--------------------------------------------
		B O O K L E T
  --------------------------------------------*/

int message_insert()
{
 int i;

 BOXBACK = 2;
 i = box("Insert a new sheet");
 return(i == 27);
}


int message_turn()
{
 int i;

 BOXBACK = 2;
 i = box("Turn the sheet");
 return(i == 27);
}


int print_half_Header()
{
 char Headertext[256];
 char pagetext[6];
 int i;
 int l;

 *Headertext = 0;

 if(HEADER_TITLE)
  {
   strcat((char *) Headertext, TITLE);
   strcat((char *) Headertext, " ");
  }

 if(HEADER_DOC)
  strcat((char *) Headertext, PRINT_FILE);

 if(HEADER_PAGES)
 {
  strcat((char *) Headertext, " Page ");
  itoa(PAGE_NUMBER, (char *) pagetext, 10);
  strcat((char *) Headertext, pagetext);
 }

 l = strlen((char *) Headertext);
 if(HEADER_CENTERED)
  {
   i = (PRINT_COLUMNS - l) / 2 - 1;
  }
 else
  i = HEADER_LEFT;

  i += PRINT_LEFT;
  l += i;
  while(i) { printchar(' '); i--;}
  fprintf(PP, "%s", Headertext);

 return(l);
}


int DoubleHeader(int gauche, int droite)
{
 int ctr;
 int i;

 if(PRINT_HEADER)
 {
  PAGE_NUMBER = gauche;
  ctr = print_half_Header();
  if(ctr)
   {
    while(ctr++ < (PRINT_COLUMNS + PRINT_LEFT)) printchar(' ');
    PAGE_NUMBER = droite;
    print_half_Header();
   }
  i = HEADER_BOTTOM + 1;
  while(i--) nextline();
  ligne_de_page = HEADER_BOTTOM + 1;
 }
}


void print_booklet(char *asktext, char *title, char *fdest, char huge *textadr, char huge *lastadr)
{
 int ctr;
 int length;
 int total_pages;
 int ENVERS;
 int AVERS;
 int FLIP;
 int gauche, droite;
 char huge *leftpage;
 char huge *rightpage;


 set_PRINTER(fdest);
 if(!AskPrint2Col(asktext)) return;

/* Calculating number of page, and last one */

 SKIP_Text(textadr, lastadr, 999);
 total_pages = PAGE_NUMBER;  /* nombre de pages */
 if(!total_pages) return;
 LAST_PAGE = min(total_pages, LAST_PAGE);

/*
 if(FIRST_PAGE > 1)
  {
   textadr = SKIP_Text(textadr, lastadr, FIRST_PAGE);
   if(!textadr) return;
   PAGE_NUMBER = FIRST_PAGE;
  }

 textadr2 = SKIP_Text(textadr, lastadr, FIRST_PAGE + 1);   /* d‚but page suivante */
 if(!textadr2) 
    print_1col(asktext, title, fdest, textadr, lastadr);
*/

 ligne_de_page = 0;        /* lines on this page so far */

 make_file_print(title);
 PP = fopen(fdest, "w");
 configure_printer();

 AVERS = 1;
 ENVERS = ((total_pages + 3) / 4) * 4;
 FLIP = 0;
 gauche = ENVERS;
 droite = AVERS;

 while(AVERS <= ENVERS)
 {
  if(DoubleHeader(gauche, droite) == 27) goto bye;

  leftpage  = SKIP_Text(textadr, lastadr, gauche);
  rightpage = SKIP_Text(textadr, lastadr, droite);

  while(ligne_de_page < PRINT_LINES)
  {
   if(gauche <= LAST_PAGE)
   {
    length = strlen((char *) leftpage);
    ctr = PrintSemiLine((char *) leftpage);
    if(ctr == -1) ctr = 0;
    while(ctr++ < (PRINT_COLUMNS + PRINT_LEFT)) printchar(' ');
    leftpage = hugepint(leftpage, length + 1);
   }
   else
   {
    ctr = 0;
    while(ctr++ < (PRINT_COLUMNS + PRINT_LEFT)) printchar(' ');
   }

   if(droite <= LAST_PAGE)
   {
    length = strlen((char *) rightpage);
    ctr = PrintSemiLine((char *) rightpage);
    if(ctr == -1) ctr = 0;
    if(ctr == strlen((char *) rightpage)) ctr++;
    rightpage = hugepint(rightpage, length + 1);
   }

  nextline();
  ligne_de_page++;
 }

 FLIP ^= 1;
 AVERS++;
 ENVERS--;
 if(AVERS <= ENVERS)
 {
  if(FLIP)
   {
    gauche = AVERS;
    droite = ENVERS;
    if(message_turn()) goto bye;
   }
  else
   {
    gauche = ENVERS;
    droite = AVERS;
    if(message_insert()) goto bye;
   }
  }
 }

bye:
 fclose(PP);
}


void print_text(char *asktext, char *title, char *fdest, char huge *textadr, char huge *lastadr)
{
 if(BOOKLET)    print_booklet(asktext, title, fdest, textadr, lastadr);
 else
 {
 if(PRINT_2COL) print_2col(asktext, title, fdest, textadr, lastadr);
 else           print_1col(asktext, title, fdest, textadr, lastadr);
 }
}


void get_serial(unsigned char bufval[MAXPRINTCODES][MAXPRINTSIZE])
{
 int num;
 int index;
 int total;

 while(*txt == ' ' || *txt == '=') txt++;
 if(*txt)
  {

  index = 0;
  total = 0;

nextline:
   bufval[index][0] = 0;
   num = 1;

   if(total < (MAXPRINTCODES * MAXPRINTSIZE))
    {
     if(kbhit() == 27) return;

nextval:
     if(get_val() == 0) goto bye;
     bufval[index][num] = GVALUE;
     bufval[index][0]  += 1;

     while(*txt == ' ') txt++;
     total++;
     if(*txt == ',') { txt++; index++; goto nextline;}
     if(num < (MAXPRINTSIZE - 1)) num++;
     goto nextval;
    }
 }

bye:
 return;
}

int get_printer_codes()
{
 unsigned char ARRAY[MAXPRINTCODES][MAXPRINTSIZE];

 memset((char *) ARRAY, '\0', MAXPRINTCODES * MAXPRINTSIZE);
 get_serial(ARRAY);

 set_array(CODES_RESET,        ARRAY[0]);
 set_array(CODES_COMPRESS_ON,  ARRAY[1]);
 set_array(CODES_COMPRESS_OFF, ARRAY[2]);
 set_array(CODES_UNDER_ON,     ARRAY[3]);
 set_array(CODES_UNDER_OFF,    ARRAY[4]);
 set_array(CODES_DRAFT,        ARRAY[5]);
 set_array(CODES_LETTER,       ARRAY[6]);
 set_array(CODES_REDUCE_ON,    ARRAY[7]);
 set_array(CODES_REDUCE_OFF,   ARRAY[8]);
 set_array(CODES_SQUIZE_ON,    ARRAY[9]);
 set_array(CODES_SQUIZE_OFF,   ARRAY[10]);

}


void set_array(unsigned char *var, unsigned char *array)
{
 int i;
 int n;

 n = array[0];
 for(i = 1; i <= n; i++) var[i] = array[i];
 if(var[1]) var[0] = n;
       else var[0] = 0;
}


