// QSLPRINT.C - Printing QSL-labels
// Written by Stefan Pfeiffer, DL1ELY, 950605
// Last Modification: 950615
// (C) 1995 by Stefan Pfeiffer, DL1ELY@DB0PKE

#include "qslprint.h"
#include "tools.h"
#include "dvideo.h"
#include "input.h"
#include "structs.h"
#include "multibnd.h"
#include "database.h"
#include <dos.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

extern unsigned char menuinvcol;
extern unsigned char menucol;
extern unsigned char passivebuttoncol;
extern unsigned char activebuttoncol;
extern char fn_path[128];
extern struct qso *firstqso;
extern struct definition *act_def;
extern struct header h;
extern char cntname[128];
extern char date[7];


void my_gotoxy(unsigned char, unsigned char);

void print_params(struct pparams *pp)
{
   void *save;
   char sel = 1;
   char res;
   char ch;
   char s[20];

   save = dsave(0,0,79,lastline);

   dfill(0,0,79,0,' ',menuinvcol);
   dfill(0,1,79,lastline,' ',menucol);

   dprint(32,0,menuinvcol,"Print-parameters");

   dprint(2,2,menucol,"Smallest paper forward of the used printer:                1/");
   dprint(2,3,menucol,"(Only 1/180 inch or 1/216 inch possible!)");
   dfill(63,2,66,2,' ',menuinvcol);
   dprint(68,2,menucol,"Inch");
   dprintf(63,2,menuinvcol,"%u",pp->unit);

   dprint(2,5,menucol,"Single forward before printing:");
   dfill(55,5,59,5,' ',menuinvcol);
   dprint(61,5,menucol,"1/10 Millimeter");
   dprintf(55,5,menuinvcol,"%u",pp->vorlauf);

   dprint(2,7,menucol,"Space between edge of paper and left edge of label:");
   dfill(55,7,59,7,' ',menuinvcol);
   dprint(61,7,menucol,"1/10 Millimeter");
   dprintf(55,7,menuinvcol,"%u",pp->etikett_rand);

   dprint(2,9,menucol,"Left margin on the label:");
   dfill(32,9,36,9,' ',menuinvcol);
   dprint(38,9,menucol,"1/10 Millimeter");
   dprintf(32,9,menuinvcol,"%u",pp->linker_rand);

   dprint(2,11,menucol,"Right margin on the label:");
   dfill(32,11,36,11,' ',menuinvcol);
   dprint(38,11,menucol,"1/10 Millimeter");
   dprintf(32,11,menuinvcol,"%u",pp->rechter_rand);

   dprint(2,13,menucol,"Upper margin on the label:");
   dfill(32,13,36,13,' ',menuinvcol);
   dprint(38,13,menucol,"1/10 Millimeter");
   dprintf(32,13,menuinvcol,"%u",pp->oberer_rand);

   dprint(2,15,menucol,"Bottom margin on the label:");
   dfill(32,15,36,15,' ',menuinvcol);
   dprint(38,15,menucol,"1/10 Millimeter");
   dprintf(32,15,menuinvcol,"%u",pp->unterer_rand);

   dprint(2,18,menucol,"Width of the label:");
   dfill(23,18,27,18,' ',menuinvcol);
   dprint(29,18,menucol,"1/10 Millimeter");
   dprintf(23,18,menuinvcol,"%u",pp->breite);

   dprint(2,20,menucol,"Height of label:");
   dfill(23,20,27,20,' ',menuinvcol);
   dprint(29,20,menucol,"1/10 Millimeter");
   dprintf(23,20,menuinvcol,"%u",pp->hoehe);

   dprint(2,23,menucol,"Vertical space between labels:");
   dfill(36,23,40,23,' ',menuinvcol);
   dprint(42,23,menucol,"1/10 Millimeter");
   dprintf(36,23,menuinvcol,"%u",pp->abstand);

   paint_but(64,20,"OK",passivebuttoncol,menucol);

   do
   {
     switch(sel)
     {
        case 1:
           sprintf(s,"%u",pp->unit);
           res = input_string(63,2,3,3,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->unit = atoi(s);
           if((pp->unit != 180) && (pp->unit != 216))
           { 
              pp->unit = 180;
              dprint(63,2,menuinvcol,"180");
           };
           break;
        case 2:
           sprintf(s,"%u",pp->vorlauf);
           res = input_string(55,5,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->vorlauf = atoi(s);
           break;
        case 3:
           sprintf(s,"%u",pp->etikett_rand);
           res = input_string(55,7,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->etikett_rand = atoi(s);
           break;
        case 4:
           sprintf(s,"%u",pp->linker_rand);
           res = input_string(32,9,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->linker_rand = atoi(s);
           break;
        case 5:
           sprintf(s,"%u",pp->rechter_rand);
           res = input_string(32,11,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->rechter_rand = atoi(s);
           break;
        case 6:
           sprintf(s,"%u",pp->oberer_rand);
           res = input_string(32,13,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->oberer_rand = atoi(s);
           break;
        case 7:
           sprintf(s,"%u",pp->unterer_rand);
           res = input_string(32,15,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->unterer_rand = atoi(s);
           break;
        case 8:
           sprintf(s,"%u",pp->breite);
           res = input_string(23,18,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->breite = atoi(s);
           break;
        case 9:
           sprintf(s,"%u",pp->hoehe);
           res = input_string(23,20,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->hoehe = atoi(s);
           break;
        case 10:
           sprintf(s,"%u",pp->abstand);
           res = input_string(36,23,4,4,INSERT|DO_TAB|DIGITS_ONLY,menuinvcol,s);
           if(res) pp->abstand = atoi(s);
           break;
        case 11:
           paint_but(64,20,"OK",activebuttoncol,menucol);
           my_gotoxy(80,lastline+1);
           ch = getch();
           if((ch == 27) || (ch == 13)) res = 0;
           if(ch == 9)
           {
              res = TAB;
              paint_but(64,20,"OK",passivebuttoncol,menucol);
           };
           if(!ch)
           {
              ch = getch();
              if(ch == 15)
              {
                 res = BACKTAB;
                 paint_but(64,20,"OK",passivebuttoncol,menucol);
              };
           };
           break;

     };

     if((res == 1)||(res == TAB))
     {
        sel++;
        if(sel>11) sel = 1;
        res = 2;
     };
     if(res == BACKTAB)
     {
        sel--;
        if(!sel) sel = 11;
        res = 2;
     };

   } while(res == 2);

   drestore(save);
   sec_free(save);
   my_gotoxy(80,lastline+1);
};

void set_def_params(struct pparams *pp)
{
   pp->unit          = 180;
   pp->vorlauf       =   0;
   pp->etikett_rand  =   0;
   pp->linker_rand   =   0;
   pp->rechter_rand  =   0;
   pp->oberer_rand   =   0;
   pp->unterer_rand  =   0;
   pp->breite        = 890;
   pp->hoehe         = 361;
   pp->abstand       =   0;
};

void save_print_params(struct pparams *pp)
{
   FILE *f;
   char s[128];

   generate_path(fn_path,"PRINTER.59","",s);
   if((f = fopen(s,"wt")) == NULL) return;

   fprintf(f,"%u\n",pp->unit);
   fprintf(f,"%u\n",pp->vorlauf);
   fprintf(f,"%u\n",pp->etikett_rand);
   fprintf(f,"%u\n",pp->linker_rand);
   fprintf(f,"%u\n",pp->rechter_rand);
   fprintf(f,"%u\n",pp->oberer_rand);
   fprintf(f,"%u\n",pp->unterer_rand);
   fprintf(f,"%u\n",pp->breite);
   fprintf(f,"%u\n",pp->hoehe);
   fprintf(f,"%u\n",pp->abstand);

   fclose(f);
};

char get_print_params(struct pparams *pp)
{
   FILE *f;
   char s[128];

   generate_path(fn_path,"PRINTER.59","",s);
   if((f = fopen(s,"rt")) == NULL) return(0);

   fgets(s,128,f);
   pp->unit = atoi(s);

   fgets(s,128,f);
   pp->vorlauf = atoi(s);

   fgets(s,128,f);
   pp->etikett_rand = atoi(s);

   fgets(s,128,f);
   pp->linker_rand = atoi(s);

   fgets(s,128,f);
   pp->rechter_rand = atoi(s);

   fgets(s,128,f);
   pp->oberer_rand = atoi(s);

   fgets(s,128,f);
   pp->unterer_rand = atoi(s);

   fgets(s,128,f);
   pp->breite = atoi(s);

   fgets(s,128,f);
   pp->hoehe = atoi(s);

   fgets(s,128,f);
   pp->abstand = atoi(s);

   fclose(f);
   return(1);
};

// Vertikaler Vorschub, Value/216stel oder Value/180stel Inch
void vertvor(UINT value, BYTE max)
{
   while(value)
   {
      fprintf(stdprn,"\x1BJ%c",value>max?max:value);
      value-=value>max?max:value;
   };
};

// Horizontaler Vorschub, Value/60stel Inch
void horzvor(UINT value)
{
  if(!value) return;
  fprintf(stdprn,"\x1B$%c%c",value%256,value>>8);
};

void test_print(struct pparams *pp)
{
  UINT x_usable;
  UINT y_usable;

  x_usable = pp->breite - pp->linker_rand - pp->rechter_rand;
  y_usable = pp->hoehe - pp->oberer_rand - pp->unterer_rand;

  vertvor(pp->vorlauf,pp->unit);
  horzvor(pp->etikett_rand);
  fprintf(stdprn,"%c",218);
  horzvor(pp->etikett_rand + pp->breite);
  fprintf(stdprn,"%c",191);

  vertvor(pp->oberer_rand,pp->unit);
  horzvor(pp->etikett_rand + pp->linker_rand);
  fprintf(stdprn,"%c",218);
  horzvor(pp->etikett_rand + pp->linker_rand + x_usable);
  fprintf(stdprn,"%c",191);

  vertvor(y_usable,pp->unit);
  horzvor(pp->etikett_rand + pp->linker_rand);
  fprintf(stdprn,"%c",192);
  horzvor(pp->etikett_rand + pp->linker_rand + x_usable);
  fprintf(stdprn,"%c",217);

  vertvor(pp->unterer_rand,pp->unit);
  horzvor(pp->etikett_rand);
  fprintf(stdprn,"%c",192);
  horzvor(pp->etikett_rand + pp->breite);
  fprintf(stdprn,"%c",217);

  vertvor(pp->abstand,pp->unit);
  horzvor(pp->etikett_rand);
  fprintf(stdprn,"%c%c%c",196,196,196);
};

void convert_print_params(struct pparams *pp1, struct pparams *pp2)
{
   pp2->vorlauf = (UINT)((float)pp1->vorlauf * MM2INCH * (float)pp1->unit);
   pp2->etikett_rand = (UINT)((float)pp1->etikett_rand * MM2INCH *(float)60);
   pp2->linker_rand = (UINT)((float)pp1->linker_rand * MM2INCH * (float)60);
   pp2->rechter_rand = (UINT)((float)pp1->rechter_rand * MM2INCH * (float)60);
   pp2->oberer_rand = (UINT)((float)pp1->oberer_rand * MM2INCH *(float)pp1->unit);
   pp2->unterer_rand = (UINT)((float)pp1->unterer_rand * MM2INCH * (float)pp1->unit);
   pp2->breite = (UINT)((float)pp1->breite * MM2INCH * (float)60);
   pp2->hoehe = (UINT)((float)pp1->hoehe * MM2INCH * (float)pp1->unit);
   pp2->abstand = (UINT)((float)pp1->abstand * MM2INCH * (float)pp1->unit);
};


#define TO_RADIO    "To Radio: "
#define TEXT1       "I'm happy to cfm our contest-QSO:"
#define TEXT2       "  Date     UTC    Mode   MHz   QRB "
#define TEXT3       "%02d.%02d.%02d  %02d:%02d   %s    %d  %ukm"
#define TEXT4       "ur number: %s  my number: %s%s"
#define TEXT5a      "pse QSL!"
#define TEXT5b      "tnx fer QSL!"
#define TEXT6       "VY 73 de %s in %s"


void print(BYTE pse,struct qso q,struct pdata pd,struct pparams pp)
{
   UINT hlp, hlp2;
   UINT rest;
   UINT needed;
   UINT unused;
   UINT x_usable;
   UINT y_usable;
   BYTE s[80];
   BYTE s1[10];
   BYTE s2[10];
   BYTE s3[5];
   BYTE *cp1;
   BYTE *cp2;

   x_usable = pp.breite - pp.linker_rand - pp.rechter_rand;
   y_usable = pp.hoehe - pp.oberer_rand - pp.unterer_rand;

   needed = pp.unit == 216? 212 : 177;
   unused = (y_usable-needed)>>1;

   if(q.hour<14) pd.day++;

   rest = y_usable;
   vertvor(pp.oberer_rand,pp.unit);

   hlp = (strlen(TO_RADIO)*CHARUNIT)+(strlen(q.call)*2*CHARUNIT);
   hlp2 = (x_usable-hlp)>>1;
   horzvor(pp.etikett_rand + pp.linker_rand + hlp2);
   fprintf(stdprn,TO_RADIO);

   fprintf(stdprn,"\x1BW%c",1);
   fprintf(stdprn,"%s",q.call);
   fprintf(stdprn,"\x1BW%c",0);
   vertvor(unused,pp.unit);
   rest-=unused;


   hlp = strlen(TEXT1)*CHARUNIT;
   hlp2 = (x_usable-hlp)>>1;
   horzvor(pp.etikett_rand + pp.linker_rand + hlp2);
   fprintf(stdprn,TEXT1);
   vertvor(pp.unit == 216 ? 54 : 45,pp.unit);
   rest -= pp.unit == 216 ? 54 : 45;

   hlp = strlen(TEXT2)*CHARUNIT;
   hlp2 = (x_usable-hlp)>>1;
   horzvor(pp.etikett_rand + pp.linker_rand + hlp2);
   fprintf(stdprn,TEXT2);
   vertvor(pp.unit == 216 ? 32 : 27,pp.unit);
   rest -= pp.unit == 216 ? 32 : 27;
   strcpy(s3,"SSB");
   if(q.rst_TX[0] != ' ')
   {
      if(q.rst_TX[2] != 'A') strcpy(s3," CW");
      else strcpy(s3,"AUR");
   };

   sprintf(s,TEXT3,pd.day,pd.mon,pd.year,q.hour,q.min,s3,pd.qrg,q.points);
   horzvor(pp.etikett_rand + pp.linker_rand + hlp2);
   fprintf(stdprn,s);
   vertvor(pp.unit == 216 ? 54 : 45,pp.unit);
   rest -= pp.unit == 216 ? 54 : 45;

   strcpy(s1,q.rst_RX);
   cp1 = s1;
   while(*cp1 == ' ') cp1++;
   strcpy(s2,q.rst_TX);
   cp2 = s2;
   while(*cp2 == ' ') cp2++;
   if(q.nr<1000) sprintf(s3,"%03d",q.nr);
   else sprintf(s3,"%04d",q.nr);
   sprintf(s,TEXT4,cp1,cp2,s3);
   hlp = strlen(s)*CHARUNIT;
   hlp2 = (x_usable-hlp)>>1;
   horzvor(pp.etikett_rand + pp.linker_rand + hlp2);
   fprintf(stdprn,s);
   vertvor(unused,pp.unit);
   rest-=unused;

   horzvor(pp.etikett_rand + pp.linker_rand + (2*CHARUNIT));
   fprintf(stdprn,pse?TEXT5a:TEXT5b);
   vertvor(pp.unit == 216 ? 36 : 30,pp.unit);
   sprintf(s,TEXT6,pd.call,pd.loc);
   horzvor(pp.etikett_rand + pp.linker_rand + (2*CHARUNIT));
   fprintf(stdprn,s);
   vertvor(pp.unit == 216 ? 36 : 30,pp.unit);
   rest -= pp.unit == 217 ? 72 : 60;
   vertvor(rest,pp.unit);
   vertvor(pp.unterer_rand,pp.unit);
};

void callsort(char huge *ptr,UINT first,UINT last,int (*fcmp)(const void *, const void *))
{
  UINT i;
  UINT j;
  UINT m;
  char s[16];

  i = first;
  j = last;
  m = (i+j)/2;

  while(i<j)
  {
    while((i<m) && (fcmp(ptr+(i*16),ptr+(m*16))<0)) i++;
    while((j>m) && (fcmp(ptr+(m*16),ptr+(j*16))<0)) j--;

    if(i!=j)
    {
      strcpy(s,ptr+(i*16));
      strcpy(ptr+(i*16),ptr+(j*16));
      strcpy(ptr+(j*16),s);
      if(m==i) m=j;
      else if(m==j) m=i;
      if(i<m) i++;
      if(j>m) j--;
    };
  };

  if(last-first>1)
  {
    if(i>first) callsort(ptr,first,i,fcmp);
    if(j<last) callsort(ptr,j,last,fcmp);
  };
};


int far cmp_call(const void *a,const void *b)
{
  return(strcmp((char *)a,(char *)b));
};


void print_qsl(struct pparams *pp)
{
   struct pdata pd;
   struct qso_mask qm;
   char huge *calls;
   unsigned sel_calls = 0;
   struct qso *q;
   char s[20];
   unsigned i;
   unsigned seg;
   char *cp;
   void *save;
   char res;

   if(!cntname[0]) return;
   load_prefixes();
   open_contest_file(cntname,act_def->band);

   dfill(0,lastline,79,lastline,' ',titlecol);

   strcpy(pd.call,h.owncall);
   strcpy(pd.loc,h.ownloc);
   strcpy(s,act_def->band);
   cp = s;
   while(isdigit(*cp)) cp++;
   *cp = 0;
   pd.qrg = atoi(s);
 
   sprintf(s,"%u",pd.qrg);
   save = make_win(30,4,45,7,menucol);

   dprint(32,5,menucol,"MHZ-Band:");
   dfill(32,6,44,6,' ',menuinvcol);
   res = input_string(31,6,8,8,DIGITS_ONLY|INSERT,menuinvcol,s);

   drestore(save);
   sec_free(save);
   my_gotoxy(80,lastline+1);

   if(!res)
   {
      kill_all_qso();
      kill_all_squares();
      kill_all_prefixes();

      my_gotoxy(80,lastline+1);

      return;
   };

   pd.qrg = atoi(s);

   s[2] = 0;
   memcpy(s,date,2);
   pd.day = atoi(s);
   memcpy(s,date+2,2);
   pd.mon = atoi(s);
   memcpy(s,date+4,2);
   pd.year = atoi(s);

   query_qso_mask(&qm);

   calls = sec_alloc(h.qso_cnt * 16);
 
   for(q = firstqso; q; q = q->next)
   {
      if(q->points && qso_match(q,&qm))
      {
         strcpy(calls+(sel_calls*16),q->barecall);
         sel_calls++;
      };
   };

   if(!sel_calls)
   {
      ok_box("Warning","No fitting QSO found!");
      
      sec_free(calls);
      kill_all_qso();
      kill_all_squares();
      kill_all_prefixes();

      my_gotoxy(80,lastline+1);

      return;
   };

   callsort(calls,0,sel_calls-1,cmp_call);

   fprintf(stdprn,"\x1Bx1");
   fprintf(stdprn,"\x1B\x7E%c",1);
   fprintf(stdprn,"\x1B\x78\x31");
   fprintf(stdprn,"\x1B\x4D");
   fprintf(stdprn,"\x1B\x70%c",0);

   vertvor(pp->vorlauf,pp->unit);

   for(i=0;i<sel_calls;i++)
   {
      strcpy(s,calls+(i*16));
      for(q=firstqso; q && strcmp(q->barecall,s); q = q->next) ;
      if(q)
      {
         print(1,*q,pd,*pp);
         vertvor(pp->abstand,pp->unit);
      };
   };

   fprintf(stdprn,"\x1B\x7E%c",0);
   fprintf(stdprn,"\xFF"); 

   sec_free(calls);
   sel_calls = 0;
   calls = NULL;

   kill_all_qso();
   kill_all_squares();
   kill_all_prefixes();

   my_gotoxy(80,lastline+1);

};

void print_tnx_qsl(struct pparams *pp)
{
   struct pdata pd;
   char call[20];
   char res;
   void *save;
   char s[40];
   struct qso *q;
   char *cp;
   char pref[5];
   char barecall[14];
   char add[4];

   strcpy(pd.call,h.owncall);
   strcpy(pd.loc,h.ownloc);
   strcpy(s,act_def->band);
   cp = s;
   while(isdigit(*cp)) cp++;
   *cp = 0;
   pd.qrg = atoi(s);

   sprintf(s,"%u",pd.qrg);
   save = make_win(30,4,45,7,menucol);

   dprint(32,5,menucol,"MHz-Band:");
   dfill(32,6,44,6,' ',menuinvcol);
   res = input_string(32,6,8,8,DIGITS_ONLY|INSERT,menuinvcol,s);

   drestore(save);
   sec_free(save);
   my_gotoxy(80,lastline+1);

   if(!res)
   {
      kill_all_qso();
      kill_all_squares();
      kill_all_prefixes();

      my_gotoxy(80,lastline+1);

      return;
   };

   pd.qrg = atoi(s);

   s[2] = 0;
   memcpy(s,date,2);
   pd.day = atoi(s);
   memcpy(s,date+2,2);
   pd.mon = atoi(s);
   memcpy(s,date+4,2);
   pd.year = atoi(s);

   if(!cntname[0]) return;
   load_prefixes();
   open_contest_file(cntname,act_def->band);

   dfill(0,lastline,79,lastline,' ',titlecol);

   fprintf(stdprn,"\x1Bx1");
   fprintf(stdprn,"\x1B\x7E%c",1);
   fprintf(stdprn,"\x1B\x78\x31");
   fprintf(stdprn,"\x1B\x4D");
   fprintf(stdprn,"\x1B\x70%c",0);

   vertvor(pp->vorlauf,pp->unit);

   save = make_win(40,5,60,8,menucol);

   dprint(42,6,menucol,"Call:");
   do
   {
      call[0] = 0;
      res = input_string(42,7,16,16,INSERT|CALL_CONVERT|UPCASE,menuinvcol,call);
      if(res && !call[0]) res = 0;
      if(res)
      {
         splitcall(call,pref,barecall,add);
         strcpy(call,barecall);

         q = firstqso;
         while(q && strcmp(q->barecall,call)) q = q->next;
         if(q)
         {
            print(0,*q,pd,*pp);
            vertvor(pp->abstand,pp->unit);
         }
         else
         {
            sprintf(s,"%s not in log!",call);
            ok_box("Warning",s);
         };
      };
   } while(res);

   drestore(save);
   sec_free(save);

   fprintf(stdprn,"\x1B\x7E%c",0);
   fprintf(stdprn,"\xFF");

   kill_all_qso();
   kill_all_squares();
   kill_all_prefixes();

   my_gotoxy(80,lastline+1);
};


