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

   Program:    PrLabel
   File:       PrL.c
   
   Version:    V1.2
   Date:       28.10.91
   Function:   Actual label printing and Interface handling routines
   
   Copyright:  SciTech Software 1991
   Author:     Andrew C. R. Martin
   Address:    SciTech Software
               23, Stag Leys,
               Ashtead,
               Surrey,
               KT21 2TD.
   Phone:      +44 (0372) 275775
   EMail:      UUCP: cbmuk!cbmuka!scitec!amartin
               JANET: andrew@uk.ac.ox.biop
               
****************************************************************************

   This program is Shareware with a suggested donation of £5.00.
   It may be freely copied and distributed for no more than a nominal charge 
   (not more than £4.00 in the U.K.) providing this header is included.
   
   The code may be modified as required, but any modifications must be
   documented so that the person responsible can be identified. If someone
   else breaks this code, I don't want to be blamed for code that does not
   work! The code may not be sold commercially without prior permission from
   the author, although it may be given away free with commercial products,
   providing it is made clear that this program is free and that the source
   code is provided with the program.

****************************************************************************

   Description:
   ============
   
   Actual label printing and interface handling routines for PrLabel.
   
   N.B. The values for spacing in SetSheet27() and SetSheet28() have been
        calculated, but never actually tested (I use 3x8 label sheets!).
        Similarly Label27() and Label28().
        
        If you find these values are wrong, please let me know28.10..


****************************************************************************

   Usage:
   ======

****************************************************************************

   Revision History:
   =================
   V1.1     17.01.92
   Changed interface to use STSLib.
   V1.2     14.09.92
   Added code for reading and writing address lists

***************************************************************************/
#include "PrLabel.h"

/**************************************************************************/
/* Macros
*/
#define NEXT(x)         (x)=(x)->next
#define ALLOCNEXT(x,y)  {  if(((x)->next=(y *)malloc(sizeof(y)))==NULL) \
                              Die("Out of Memory!"); \
                           NEXT(x); \
                           (x)->next=NULL; \
                        }
#define LAST(x)         while((x)->next != NULL) NEXT(x)
#define TOGGLE(x)       (x) = (!(x))
#define TERMINATE(x) {  int j;               \
                        for(j=0; x[j]; j++)  \
                        {  if(x[j] == '\n')  \
                           {  x[j] = '\0';   \
                              break;         \
                     }  }  }

/**************************************************************************/
/*>SetSheet38(APTR object)
   -----------------------
   Sets sheet pattern to 3x8
   28.10.91 Original
   14.09.92 Documented
*/
SetSheet38(APTR object)
{
   int j;
   
   for(j=0;j<8;j++)
   {
      label[0][j].x =  0;
      label[1][j].x = 28;
      label[2][j].x = 56;
   }
   
   for(j=0;j<3;j++)
   {
      label[j][0].y =  0;
      label[j][1].y =  8;
      label[j][2].y = 16;
      label[j][3].y = 25;
      label[j][4].y = 34;
      label[j][5].y = 43;
      label[j][6].y = 52;
      label[j][7].y = 60;
   }
   
   SheetType = THREE_EIGHT;
   
   return(0);
}

/**************************************************************************/
/*>SetSheet28(APTR object)
   -----------------------
   Sets sheet pattern to 2x8
   28.10.91 Original
   14.09.92 Documented
*/
SetSheet28(APTR object)
{
   int j;
   
   for(j=0;j<8;j++)
   {
      label[0][j].x =  0;
      label[1][j].x = 43;
      label[2][j].x = LINELENGTH+10; /* Make sure this won't be printed */
   }

   for(j=0;j<3;j++)
   {
      label[j][0].y =  0;
      label[j][1].y =  8;
      label[j][2].y = 16;
      label[j][3].y = 25;
      label[j][4].y = 34;
      label[j][5].y = 43;
      label[j][6].y = 52;
      label[j][7].y = 60;
   }
   
   SheetType = TWO_EIGHT;
   
   return(0);
}

/**************************************************************************/
/*>SetSheet27(APTR object)
   -----------------------
   Sets sheet pattern to 2x7
   28.10.91 Original
   14.09.92 Documented
*/
SetSheet27(APTR object)
{
   int j;

   for(j=0;j<8;j++)
   {
      label[0][j].x =  0;
      label[1][j].x = 42;
      label[2][j].x = LINELENGTH+10; /* Make sure this won't be printed */
   }
   
   for(j=0;j<3;j++)
   {
      label[j][0].y =  0;
      label[j][1].y =  9;
      label[j][2].y = 19;
      label[j][3].y = 29;
      label[j][4].y = 39;
      label[j][5].y = 49;
      label[j][6].y = 59;
      label[j][7].y = PAGELENGTH+10; /* Make sure this won't be printed */
   }

   SheetType = TWO_SEVEN;
   
   return(0);
}

/**************************************************************************/
/*>SetPos11(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos11(APTR object)
{
   TOGGLE(label[0][0].print);
   return(0);
}

/**************************************************************************/
/*>SetPos12(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos12(APTR object)
{
   TOGGLE(label[0][1].print);
   return(0);
}

/**************************************************************************/
/*>SetPos13(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos13(APTR object)
{
   TOGGLE(label[0][2].print);
   return(0);
}

/**************************************************************************/
/*>SetPos14(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos14(APTR object)
{
   TOGGLE(label[0][3].print);
   return(0);
}

/**************************************************************************/
/*>SetPos15(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos15(APTR object)
{
   TOGGLE(label[0][4].print);
   return(0);
}

/**************************************************************************/
/*>SetPos16(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos16(APTR object)
{
   TOGGLE(label[0][5].print);
   return(0);
}

/**************************************************************************/
/*>SetPos17(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos17(APTR object)
{
   TOGGLE(label[0][6].print);
   return(0);
}

/**************************************************************************/
/*>SetPos18(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos18(APTR object)
{
   TOGGLE(label[0][7].print);
   return(0);
}

/**************************************************************************/
/*>SetPos21(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos21(APTR object)
{
   TOGGLE(label[1][0].print);
   return(0);
}

/**************************************************************************/
/*>SetPos22(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos22(APTR object)
{
   TOGGLE(label[1][1].print);
   return(0);
}

/**************************************************************************/
/*>SetPos23(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos23(APTR object)
{
   TOGGLE(label[1][2].print);
   return(0);
}

/**************************************************************************/
/*>SetPos24(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos24(APTR object)
{
   TOGGLE(label[1][3].print);
   return(0);
}

/**************************************************************************/
/*>SetPos25(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos25(APTR object)
{
   TOGGLE(label[1][4].print);
   return(0);
}

/**************************************************************************/
/*>SetPos26(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos26(APTR object)
{
   TOGGLE(label[1][5].print);
   return(0);
}

/**************************************************************************/
/*>SetPos27(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos27(APTR object)
{
   TOGGLE(label[1][6].print);
   return(0);
}

/**************************************************************************/
/*>SetPos28(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos28(APTR object)
{
   TOGGLE(label[1][7].print);
   return(0);
}

/**************************************************************************/
/*>SetPos31(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos31(APTR object)
{
   TOGGLE(label[2][0].print);
   return(0);
}

/**************************************************************************/
/*>SetPos32(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos32(APTR object)
{
   TOGGLE(label[2][1].print);
   return(0);
}

/**************************************************************************/
/*>SetPos33(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos33(APTR object)
{
   TOGGLE(label[2][2].print);
   return(0);
}

/**************************************************************************/
/*>SetPos34(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos34(APTR object)
{
   TOGGLE(label[2][3].print);
   return(0);
}

/**************************************************************************/
/*>SetPos35(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos35(APTR object)
{
   TOGGLE(label[2][4].print);
   return(0);
}

/**************************************************************************/
/*>SetPos36(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos36(APTR object)
{
   TOGGLE(label[2][5].print);
   return(0);
}

/**************************************************************************/
/*>SetPos37(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos37(APTR object)
{
   TOGGLE(label[2][6].print);
   return(0);
}

/**************************************************************************/
/*>SetPos38(APTR object)
   ---------------------
   React to click on a label gadget
   28.10.91 Original
   14.09.92 Documented
*/
SetPos38(APTR object)
{
   TOGGLE(label[2][7].print);
   return(0);
}

/**************************************************************************/
/*>PrintLabels(APTR object)
   ------------------------
   Actually prints the labels.
   28.10.91 Original
   14.09.92 Documented
*/
PrintLabels(APTR object)
{
   int  labelcount,
        j,
        k;
   /* This is only declared as static, to get it off the stack. Once the
      stack resizing option is documented for Lattice C, this can be used
      instead.
   */
   static char PageBuffer[PAGELENGTH][LINELENGTH];
   ADDR *p;
   
   /* Move to current address label and copy buffers into linked list */
   for(p=address,j=0; p!=NULL && j<CurLabel; NEXT(p), j++);
   strcpy(p->line[0], Line1SIBuff);
   strcpy(p->line[1], Line2SIBuff);
   strcpy(p->line[2], Line3SIBuff);
   strcpy(p->line[3], Line4SIBuff);
   strcpy(p->line[4], Line5SIBuff);
   strcpy(p->line[5], Line6SIBuff);
   strcpy(p->line[6], Line7SIBuff);

   /* Blank the buffer */
   BlankBuffer(PageBuffer);
   
   /* If there's only one label defined, we'll print it at each active
      label position
   */
   if(NLabel == 1)
   {
      for(j=0;j<3;j++)
         for(k=0;k<8;k++)
            if(label[j][k].print) PrintAt(PageBuffer,label[j][k].x,label[j][k].y,0);
   }
   else
   {
      labelcount = 0;
      for(j=0;j<3;j++)
         for(k=0;k<8;k++)
            if(label[j][k].print) 
            {
               if(labelcount < NLabel)
                  PrintAt(PageBuffer, label[j][k].x, label[j][k].y, labelcount++);
            }
   }
   
   DumpBuffer(PageBuffer);

   /* Reactivate line1 gadget */
   GoLine1((APTR)1);
   
   return(0);
}

/**************************************************************************/
/*>PrevLabel(APTR object)
   ----------------------
   Step to the previous label.
   28.10.92 Original
   14.09.92 Documented
*/
PrevLabel(APTR object)
{
   ADDR *p;
   int  j;
   
   /* Move to current address label and copy buffers into linked list */
   for(p=address,j=0; p!=NULL && j<CurLabel; NEXT(p), j++);
   strcpy(p->line[0], Line1SIBuff);
   strcpy(p->line[1], Line2SIBuff);
   strcpy(p->line[2], Line3SIBuff);
   strcpy(p->line[3], Line4SIBuff);
   strcpy(p->line[4], Line5SIBuff);
   strcpy(p->line[5], Line6SIBuff);
   strcpy(p->line[6], Line7SIBuff);

   CurLabel--;
   
   if(CurLabel < 0) CurLabel = 0;
   
   /* Put vales for this label in buffers */
   for(p=address,j=0; p!=NULL && j<CurLabel; NEXT(p), j++);
   strcpy(Line1SIBuff, p->line[0]);
   strcpy(Line2SIBuff, p->line[1]);
   strcpy(Line3SIBuff, p->line[2]);
   strcpy(Line4SIBuff, p->line[3]);
   strcpy(Line5SIBuff, p->line[4]);
   strcpy(Line6SIBuff, p->line[5]);
   strcpy(Line7SIBuff, p->line[6]);
   
   RefreshGList(Line1,Window,NULL,7);
   
   /* Reactivate line1 gadget */
   GoLine1((APTR)1);
   
   return(0);
}

/**************************************************************************/
/*>NextLabel(APTR object)
   ----------------------
   Step to the next label.
   28.10.92 Original
   14.09.92 Documented
*/
NextLabel(APTR object)
{
   ADDR *p;
   int  j;

   /* Move to current address label and copy buffers into linked list */
   for(p=address,j=0; p!=NULL && j<CurLabel; NEXT(p), j++);
   strcpy(p->line[0], Line1SIBuff);
   strcpy(p->line[1], Line2SIBuff);
   strcpy(p->line[2], Line3SIBuff);
   strcpy(p->line[3], Line4SIBuff);
   strcpy(p->line[4], Line5SIBuff);
   strcpy(p->line[5], Line6SIBuff);
   strcpy(p->line[6], Line7SIBuff);
   
   CurLabel++;
   p = address;
   
   /* Allocate space for next address if necessary */
   while(NLabel <= CurLabel)
   {
      LAST(p);
      ALLOCNEXT(p,ADDR);
      if(!p)
      {
         ReqMessage(Window,"No memory for next label!",0);
      }
      else
      {
         NLabel++;
         p->line[0][0] = '\0';
         p->line[1][0] = '\0';
         p->line[2][0] = '\0';
         p->line[3][0] = '\0';
         p->line[4][0] = '\0';
         p->line[5][0] = '\0';
         p->line[6][0] = '\0';
         p->next = NULL;
      }
   }
   
   /* Move to current address label and put values in buffers */
   for(p=address,j=0; p!=NULL && j<CurLabel; NEXT(p), j++);
   strcpy(Line1SIBuff,p->line[0]);
   strcpy(Line2SIBuff,p->line[1]);
   strcpy(Line3SIBuff,p->line[2]);
   strcpy(Line4SIBuff,p->line[3]);
   strcpy(Line5SIBuff,p->line[4]);
   strcpy(Line6SIBuff,p->line[5]);
   strcpy(Line7SIBuff,p->line[6]);

   RefreshGList(Line1,Window,NULL,7);

   /* Reactivate line1 gadget */
   GoLine1((APTR)1);
   
   return(0);
}

/**************************************************************************/
/*>KillLabel(APTR object)
   ----------------------
   Kill the current label unless only 1 left
   28.10.92 Original
   14.09.92 Documented
*/
KillLabel(APTR object)
{
   ADDR *p;
   int  j;
   
   if(NLabel > 1)
   {
      /* Deal with special case */
      if(CurLabel == 0)
      {
         p = address->next;
         free(address);
         address = p;
      }
      else
      {
         ADDR *q;
         /* Move to previous address label in list */
         for(p=address,j=0; p!=NULL && j<CurLabel-1; NEXT(p), j++);
         /* Save the next pointer from the address label we're going to kill */
         q = p->next->next;
         /* Kill the address label */
         free(p->next);
         /* Update the pointer */
         p->next = q;
         /* Move on if there's another address label */
         if(q)
            p = q;
         else
            CurLabel--;
      }
      
      /* Decrement number of address labels */
      NLabel--;
      
      /* Refresh buffers */
      for(p=address,j=0; p!=NULL && j<CurLabel; NEXT(p), j++);
      strcpy(Line1SIBuff, p->line[0]);
      strcpy(Line2SIBuff, p->line[1]);
      strcpy(Line3SIBuff, p->line[2]);
      strcpy(Line4SIBuff, p->line[3]);
      strcpy(Line5SIBuff, p->line[4]);
      strcpy(Line6SIBuff, p->line[5]);
      strcpy(Line7SIBuff, p->line[6]);
   
      RefreshGList(Line1,Window,NULL,7);
   }
   
   /* Reactivate line1 gadget */
   GoLine1((APTR)1);
   
   return(0);
}

/**************************************************************************/
/*>PrintAt(char PageBuffer[PAGELENGTH][LINELENGTH], int xpos, int ypos,
           int labelnum)
   --------------------------------------------------------------------
   Fill in the buffer for a label at a particular position
   28.10.92 Original
   14.09.92 Documented
*/
PrintAt(char PageBuffer[PAGELENGTH][LINELENGTH],
        int xpos,
        int ypos,
        int labelnum)
{
   int j,
       k;
   ADDR *p;

   /* Set p to point to the address item in which we're interested */
   for(p=address,j=0; p!=NULL && j<labelnum; NEXT(p), j++);
   
   /* For each line of an address */
   for(j=0;j<NLABLIN; j++)
   {
      /* Break out if we're off the page */
      if(ypos+j >= PAGELENGTH) continue;
      
      /* For each character in the line */
      for(k=0;k<strlen(p->line[j]);k++)
      {
         /* Break out if we're off the page */
         if(xpos+k >= LINELENGTH) break;
         
         /* Copy the characters into the page buffer */
         PageBuffer[ypos+j][xpos+k] = p->line[j][k];
      }
   }
   return(0);
}

/**************************************************************************/
/*>DumpBuffer(char PageBuffer[PAGELENGTH][LINELENGTH])
   ---------------------------------------------------
   Dump the buffer to the printer
   28.10.92 Original
   14.09.92 Documented
*/
DumpBuffer(char PageBuffer[PAGELENGTH][LINELENGTH])
{
   int j;
   struct FileHandle *fh;
   
   if(fh=(struct FileHandle *)Open("PRT:",MODE_OLDFILE))
   {
      /* For each line */
      for(j=0; j<PAGELENGTH; j++)
      {
         /* Ensure line is correctly terminated */
         PageBuffer[j][LINELENGTH-1] = '\0';
         /* Dump to the printer */
         Write(fh,PageBuffer[j],strlen(PageBuffer[j]));
         Write(fh,"\n",1);
      }
      Close(fh);
   }
   
   return(0);
}

/**************************************************************************/
/*>BlankBuffer(char PageBuffer[PAGELENGTH][LINELENGTH])
   ----------------------------------------------------
   Clear the print buffer
   28.10.92 Original
   14.09.92 Documented
*/
BlankBuffer(char PageBuffer[PAGELENGTH][LINELENGTH])
{
   int j,
       k;

   for(j=0;j<PAGELENGTH;j++)
   {
      for(k=0;k<LINELENGTH;k++)
         PageBuffer[j][k] = ' ';
      PageBuffer[j][LINELENGTH-1] = '\0';
   }
      
   return(0);
}

/**************************************************************************/
/*>GoLine1(APTR object)
   --------------------
   Move to label line 1 by activating the gadget
   28.10.91 Original
   14.09.92 Documented
*/
GoLine1(APTR object)
{
   ActivateGadget(Line1,Window,NULL);
   return(0);
}

/**************************************************************************/
/*>GoLine2(APTR object)
   --------------------
   Move to label line 2 by activating the gadget
   28.10.91 Original
   14.09.92 Documented
*/
GoLine2(APTR object)
{
   ActivateGadget(Line2,Window,NULL);
   return(0);
}

/**************************************************************************/
/*>GoLine3(APTR object)
   --------------------
   Move to label line 3 by activating the gadget
   28.10.91 Original
   14.09.92 Documented
*/
GoLine3(APTR object)
{
   ActivateGadget(Line3,Window,NULL);
   return(0);
}

/**************************************************************************/
/*>GoLine4(APTR object)
   --------------------
   Move to label line 4 by activating the gadget
   28.10.91 Original
   14.09.92 Documented
*/
GoLine4(APTR object)
{
   ActivateGadget(Line4,Window,NULL);
   return(0);
}

/**************************************************************************/
/*>GoLine5(APTR object)
   --------------------
   Move to label line 5 by activating the gadget
   28.10.91 Original
   14.09.92 Documented
*/
GoLine5(APTR object)
{
   ActivateGadget(Line5,Window,NULL);
   return(0);
}

/**************************************************************************/
/*>GoLine6(APTR object)
   --------------------
   Move to label line 6 by activating the gadget
   28.10.91 Original
   14.09.92 Documented
*/
GoLine6(APTR object)
{
   ActivateGadget(Line6,Window,NULL);
   return(0);
}

/**************************************************************************/
/*>GoLine7(APTR object)
   --------------------
   Move to label line 7 by activating the gadget
   28.10.91 Original
   14.09.92 Documented
*/
GoLine7(APTR object)
{
   ActivateGadget(Line7,Window,NULL);
   return(0);
}

/**************************************************************************/
/*>Label38(void)
   -------------
   Set the gadget labelling for labels 3x8
   28.10.91 Original
   14.09.92 Documented
*/
Label38(void)
{
   struct IntuiText *itext;
   
   /* Label the Y-axis */
   itext = MakeText(NULL,"6",1,97,mb+14,0);
   MakeText(itext,"7",1,97,mb+28,0);
   MakeText(itext,"7",1,97,mb+42,0);
   MakeText(itext,"7",1,97,mb+56,0);
   MakeText(itext,"7",1,97,mb+70,0);
   MakeText(itext,"7",1,97,mb+84,0);
   MakeText(itext,"7",1,97,mb+98,0);
   MakeText(itext,"3",1,97,mb+112,0);

   /* Label the X-axis */
   MakeText(itext,"26",1,15,mb+125,0);
   MakeText(itext,"26",1,43,mb+125,0);
   MakeText(itext,"20",1,71,mb+125,0);

   PrintIText(Window->RPort,itext,0,-8);

   FreeIText(itext);

   return(0);
}

/**************************************************************************/
/*>Label28(void)
   -------------
   Set the gadget labelling for labels 2x8
   28.10.91 Original
   14.09.92 Documented
*/
Label28(void)
{
   struct IntuiText *itext;
   
   /* Label the Y-axis */
   itext = MakeText(NULL,"6",1,72,mb+14,0);
   MakeText(itext,"7",1,72,mb+28,0);
   MakeText(itext,"7",1,72,mb+42,0);
   MakeText(itext,"7",1,72,mb+56,0);
   MakeText(itext,"7",1,72,mb+70,0);
   MakeText(itext,"7",1,72,mb+84,0);
   MakeText(itext,"7",1,72,mb+98,0);
   MakeText(itext,"3",1,72,mb+112,0);

   /* Label the X-axis */
   MakeText(itext,"39",1,15,mb+125,0);
   MakeText(itext,"34",1,43,mb+125,0);

   PrintIText(Window->RPort,itext,0,-8);

   FreeIText(itext);

   return(0);
}

/**************************************************************************/
/*>Label27(void)
   -------------
   Set the gadget labelling for labels 2x7
   28.10.91 Original
   14.09.92 Documented
*/
Label27(void)
{
   struct IntuiText *itext;
   
   /* Label the Y-axis */
   itext = MakeText(NULL,"7",1,72,mb+14,0);
   MakeText(itext,"7",1,72,mb+28,0);
   MakeText(itext,"7",1,72,mb+42,0);
   MakeText(itext,"7",1,72,mb+56,0);
   MakeText(itext,"7",1,72,mb+70,0);
   MakeText(itext,"7",1,72,mb+84,0);
   MakeText(itext,"4",1,72,mb+98,0);

   /* Label the X-axis */
   MakeText(itext,"39",1,15,mb+111,0);
   MakeText(itext,"34",1,43,mb+111,0);

   PrintIText(Window->RPort,itext,0,-8);

   FreeIText(itext);

   return(0);
}

/**************************************************************************/
/* Displays an About message
   28.10.91 Original
   17.01.92 Updated for distribution
   14.09.92 Documented
*/
About(APTR object)
{
   struct IntuiText *itext1,
                    *itext2,
                    *itext3,
                    *oktext;
   
   oktext  = MakeText(NULL,"OK",1,0,0,0);

   itext1 = MakeText(NULL,"PrLabel V1.2",      1,52, 0,0);
   MakeText(itext1,"Label Printing Utility",   1,12,10,0);
   MakeText(itext1,"SciTech Software ©1992",   1,12,20,0);
   MakeText(itext1," ",                        1, 0,30,0);
   MakeText(itext1,"This program is shareware",1, 0,40,0);
   MakeText(itext1,"and uses the STSLib",      1, 0,50,0);
   MakeText(itext1,"gadget and menu library",  1, 0,60,0);
   
   itext2 = MakeText(NULL,"PrLabel V1.2",      1,52, 0,0);
   MakeText(itext2,"Suggested fee £5.00",      1,24,10,0);
   MakeText(itext2," ",                        1, 0,20,0);
   MakeText(itext2,"STSLib provides 3D-look",  1, 0,30,0);
   MakeText(itext2,"gadgets and menu support", 1, 0,40,0);
   MakeText(itext2,"under V1.3 and V2.0",      1, 0,50,0);
   MakeText(itext2," ",                        1, 0,60,0);
   MakeText(itext2,"STSLib is £20.00 from:",   1, 0,70,0);
   
   itext3 = MakeText(NULL,"SciTech Software",  1, 0, 0,0);
   MakeText(itext3,"23, Stag Leys,",           1, 0,10,0);
   MakeText(itext3,"Ashtead,",                 1, 0,20,0);
   MakeText(itext3,"Surrey",                   1, 0,30,0);
   MakeText(itext3,"KT21 2TD.",                1, 0,40,0);
   MakeText(itext3," ",                        1, 0,50,0);
   MakeText(itext3,"Tel.: +44(0372)275775",    1, 0,60,0);

   STSAutoRequest(NULL,itext1,oktext,oktext,NULL,NULL,0,0);
   STSAutoRequest(NULL,itext2,oktext,oktext,NULL,NULL,0,0);
   STSAutoRequest(NULL,itext3,oktext,oktext,NULL,NULL,0,0);
   
   FreeIText(itext1);
   FreeIText(itext2);
   FreeIText(itext3);
   
   return(0);
}
/**************************************************************************/
/*>ReadList(APTR object)
   ---------------------
   Reads in an address list
   31.05.92 Original
   14.09.92 Tidied for release
*/
#include "myio.h"
#define  MAXBUFF 400

ReadList(APTR object)
{
   ADDR     *p;
   int      j,
            first;
   IOBUFF   iobuff;
   char     buffer[MAXBUFF],
            fbuff[320],
            buff2[80],
            *ptr;
   struct   FileHandle  *fh;
   static   char  fname[160],
                  fdir[160];

   if(GetAFile(AslBase,Window,NULL,"Read address list",fname,fdir,fbuff))
   {
      if((fh = (struct FileHandle *)Open(fbuff,MODE_OLDFILE)) == NULL)
      {
         ReqMessage2(Window,"Unable to open file",fbuff,0);
      }
      else
      {
         /* Move to end of current address label list */
         p = address;
         LAST(p);
         first = TRUE;
   
         /* Read in a record at a time from the file */
         iobuff.firstcall = TRUE;
         while(mygetsbuff(fh,buffer,MAXBUFF,&iobuff))
         {
            TERMINATE(buffer);
            
            for(j=0, ptr=buffer; j<7 && *ptr; j++)
            {
               /* Blank the line buffer */
               p->line[j][0] = '\0';
               
               /* Extract a line from the buffer, using the global
                  separator character as a record delimiter
               */
               ptr = GetLine(ptr,buff2,GlobSepChar);
               strcpy(p->line[j],buff2);
            }

            if(first)
            {
               strcpy(Line1SIBuff,p->line[0]);
               strcpy(Line2SIBuff,p->line[1]);
               strcpy(Line3SIBuff,p->line[2]);
               strcpy(Line4SIBuff,p->line[3]);
               strcpy(Line5SIBuff,p->line[4]);
               strcpy(Line6SIBuff,p->line[5]);
               strcpy(Line7SIBuff,p->line[6]);
               
               first = FALSE;
            }

            /* Allocate space for the next one */
            ALLOCNEXT(p,ADDR);
            if(!p)
            {
               ReqMessage(Window,"No memory for next label!",0);
            }
            else
            {
               NLabel++;
               p->line[0][0] = '\0';
               p->line[1][0] = '\0';
               p->line[2][0] = '\0';
               p->line[3][0] = '\0';
               p->line[4][0] = '\0';
               p->line[5][0] = '\0';
               p->line[6][0] = '\0';
               p->next = NULL;
            }
               
         }
         Close(fh);
      }
   }

   RefreshGList(Line1,Window,NULL,7);

   /* Reactivate line1 gadget */
   GoLine1((APTR)1);
   
   return(0);
}
/**************************************************************************/
/*>char *GetLine(char *inbuff, char *outbuff, char delim)
   ------------------------------------------------------
   Gets a string out of inbuff into outbuff delimited by delim. Returns
   pointer within inbuff, after outbuff extracted.
   31.05.92 Original
   14.09.92 Documented
*/

char *GetLine(char *inbuff, char *outbuff, char delim)
{
   int i;
   
   for(i=0; inbuff[i]!='\0' && inbuff[i] != delim; i++) outbuff[i] = inbuff[i];
   outbuff[i] = '\0';
   return(inbuff+i+1);
}

/**************************************************************************/
/* SaveList(APTR object)
   ---------------------
   Writes out an address list to a file
   14.09.92 Original
*/
SaveList(APTR object)
{
   ADDR                 *p;
   int                  j;
   char                 buffer[568],
                        fbuff[256];
   struct   FileHandle  *fh;
   static   char        fname[160],
                        fdir[160];

   if(GetAFile(AslBase,Window,NULL,"Write address list",fname,fdir,fbuff))
   {
      if((fh = (struct FileHandle *)Open(fbuff,MODE_NEWFILE)) == NULL)
      {
         ReqMessage2(Window,"Unable to open file",fbuff,0);
      }
      else
      {
         /* Move to start of address label list */
         for(p = address; p!=NULL; NEXT(p))
         {
            /* Build the lines into the buffer */
            buffer[0] = '\0';

            for(j=0;j<7;j++)
            {
               int len;
               len           = strlen(buffer);
               if(len)
               {
                  buffer[len]   = GlobSepChar;
                  buffer[len+1] = '\0';
               }
               strcat(buffer,p->line[j]);
            }

            /* Write buffer to the file */
            myputs(fh,buffer);
            myputs(fh,"\n");
         }
         Close(fh);
      }
   }

   /* Reactivate line1 gadget */
   GoLine1((APTR)1);
   
   return(0);
}

/**************************************************************************/
/*>CreateIText(struct IntuiText  *str, SHORT left, SHORT top, UBYTE *mesg)
   -----------------------------------------------------------------------
   Build a string into an IntuiText structure. Used for ReqMessage2()
   14.09.92 Extracted from my general support library
*/
static struct TextAttr CIT_TOPAZ80 = {
   (STRPTR)"topaz.font",
   TOPAZ_EIGHTY,0,0
};

CreateIText(struct IntuiText  *str,
            SHORT             left,
            SHORT             top,
            UBYTE             *mesg)
{
   str->FrontPen  = 0;
   str->BackPen   = 1;
   str->DrawMode  = JAM1;
   str->LeftEdge  = left;
   str->TopEdge   = top;
   str->ITextFont = &CIT_TOPAZ80;
   str->IText     = mesg;
   str->NextText  = NULL;
   return(0);
}
/**************************************************************************/
/*>ReqMessage2(struct Window *wind, char *string1, char *string2, int flag)
   ------------------------------------------------------------------------
   Display a 2 line requester message. If flag is TRUE, provide both OK
   and CANCEL; else just OK.
   14.09.92 Extracted from my general support library. OK it should use
            STSLib, but I was in a hurry!
*/
#define MAX(a,b) (((a)>(b)) ? (a) : (b))

ReqMessage2(struct Window *wind,
            char          *string1,
            char          *string2,
            int           flag)
{
   struct IntuiText  IText1,
                     IText2,
                     OK,
                     CANCEL;
   int               clen,
                     plen,
                     offset = 32;
   
   clen = MAX(strlen(string1),strlen(string2));
   plen = clen * 8;

   CreateIText(&IText1,offset+4*(clen-strlen(string1)),25,string1);
   CreateIText(&IText2,offset+4*(clen-strlen(string2)),35,string2);
   IText1.NextText = &IText2;

   CreateIText(&OK,AUTOLEFTEDGE,AUTOTOPEDGE,"OK");
   CreateIText(&CANCEL,AUTOLEFTEDGE,AUTOTOPEDGE,"CANCEL");
   
   if(flag)
      return(STSAutoRequest(wind,&IText1,&OK,&CANCEL,NULL,NULL,plen+64,110));
   else
      return(STSAutoRequest(wind,&IText1,&OK,&OK,NULL,NULL,plen+64,110));
   
   return(0);
}
