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

   Program:    PrLabel
   File:       main.c
   
   Version:    V1.2
   Date:       28.10.91
   Function:   Main routine
   
   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:
   ============
   PrLabel is a program to print text for laser labels.

   It uses STSLib to create 3D-look gadgets (under AmigaDOS V1.3 and V2.0)
   and menus which will resize with the system default font.
   
   STSLib is available from SciTech Software for £20.00. This includes a 
   full printed manual (>50 A5 pages) and the latest version of STSLib on
   disk with source code.

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

   Usage:
   ======
   PrLabel [-27][-28][-38]

   From the CLI, PrLabel may be invoked with one of the flags shown to 
   select the label layout. This defaults to 3x8.

   From the Workbench, the Tooltype field may be set to one of:
   FORMAT=27
   FORMAT=28
   FORMAT=38
   to get the same result.

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

   Revision History:
   =================
   V1.1     17.01.92
   Changed interface to use STSLib.
   V1.2     14.09.92
   Program now reads and write address files using a TOOLTYPE defined
   separator
   

***************************************************************************/
#define MAIN 1

#include "PrLabel.h"

extern struct WBStartup *WBenchMsg; /* This is so we can get the program name */

/**************************************************************************/
/*>main(int argc, char **argv)
   ---------------------------
   Main routine opens libs, gets tooltypes or command line parameters,
   allocates first label, then sits in IDCMP loop.
   28.10.91 Original
   14.09.92 Added new tooltype/parameter as separator for addresses.
            Added documentation for routine.
*/
main(int argc,
     char **argv)
{
   /* Disk object structure and char pointer for parsing tool types */
   struct DiskObject    *DiskObj = NULL;
   char                 *valptr;

   /* Variables for IDCMP handling */
   struct IntuiMessage  *message = NULL;
   ULONG                Signals;
   ULONG                MIClass;
   USHORT               MICode;
   APTR                 MIAddress;
   

   /* Set default sheet type and separator   */
   SetSheet38((APTR)1);
   GlobSepChar = ',';

   OpenLibraries();

   if(argc == 0)  /* Started from Workbench  */
   {
      if(DiskObj = (struct DiskObject *)GetDiskObject(WBenchMsg->sm_ArgList->wa_Name))
      {
         if(MatchToolValue(FindToolType(DiskObj->do_ToolTypes,"FORMAT"),"38"))
            SetSheet38((APTR)1);
         if(MatchToolValue(FindToolType(DiskObj->do_ToolTypes,"FORMAT"),"28"))
            SetSheet28((APTR)1);
         if(MatchToolValue(FindToolType(DiskObj->do_ToolTypes,"FORMAT"),"27"))
            SetSheet27((APTR)1);
         if((valptr = FindToolType(DiskObj->do_ToolTypes,"SEPARATOR")) != NULL)
            GlobSepChar = valptr[0];
         FreeDiskObject(DiskObj);
      }
      else
      {
         Die("Unable to get disk object information.");
      }  
   }
   else           /* Started from CLI        */
   {
      while(--argc)
      {
         argv++;
         if(argv[0][0] == '?')
         {
            Usage();
         }
         else if(argv[0][0] == '-')
         {
            switch(argv[0][1])
            {
            case '3':
               SetSheet38((APTR)1);
               break;
            case '2':
               {
                  switch(argv[0][2])
                  {
                  case '7':
                     SetSheet27((APTR)1);
                     break;
                  case '8':
                     SetSheet28((APTR)1);
                     break;
                  default:
                     Usage();
                  }
               }
               break;
            case 's':
            case 'S':
               GlobSepChar = argv[0][2];
               break;
            default:
               Usage();
            }
         }
      }
   }

   OpenDisplay();

   switch(SheetType)
   {
   case THREE_EIGHT:
      Label38();
      break;
   case TWO_EIGHT:
      Label28();
      break;
   case TWO_SEVEN:
      Label27();
      break;
   default:
      break;
   }

   /* Allocate space for first item in address label list */
   address = (ADDR *)malloc(sizeof(ADDR));
   if(!address)
   {
      Die("Unable to allocate memory");
   }
   address->line[0][0] = '\0';
   address->line[1][0] = '\0';
   address->line[2][0] = '\0';
   address->line[3][0] = '\0';
   address->line[4][0] = '\0';
   address->line[5][0] = '\0';
   address->line[6][0] = '\0';
   address->prev       = NULL;
   address->next       = NULL;

   /* Initialise so we don't print any labels to start */
   ClearPrint();

   /* Activate the first text line gadget */
   GoLine1((APTR)1);
   
   /* Main program loop */
   for(;;)
   {
      /* Wait for messages from window */
      Signals = Wait(1<<Window->UserPort->mp_SigBit);
      /* Handle messages from the window */
      while (message = (struct IntuiMessage *)
         GetMsg(Window->UserPort))
      {
         MIClass   = message->Class;
         MICode    = message->Code;
         MIAddress = message->IAddress;
         

         ReplyMsg(message);

         switch (MIClass)
         {
            case MENUPICK:
               if ((MICode) != MENUNULL)
               {
                  HandleMenu(MICode);
               }
               break;

            case GADGETDOWN:
               break;

            case GADGETUP:
               HandleEvent(MIAddress);
               break;
               
            case CLOSEWINDOW:
               QuitProgram((APTR)1);
               break;

            default:
               break;
         }
      }
   }

   return(0);
}


/**************************************************************************/
/*>void HandleEvent(APTR object)
   -----------------------------
   Dispatches events after menu or gadget activity.
   28.10.91 Original
   31.05.92 Added Read and Save
   14.09.92 ANSI'd. Added documentation for routine.
*/
void HandleEvent(APTR object)
{
  if (object == (APTR)MenuItem1) { ReadList(object); return; }
  if (object == (APTR)MenuItem2) { SaveList(object); return; }
  if (object == (APTR)MenuItem3) { About(object); return; }
  if (object == (APTR)MenuItem4) { QuitProgram(object); return; }
  if (object == (APTR)pos11) { SetPos11(object); return; }
  if (object == (APTR)pos12) { SetPos12(object); return; }
  if (object == (APTR)pos14) { SetPos14(object); return; }
  if (object == (APTR)pos13) { SetPos13(object); return; }
  if (object == (APTR)pos15) { SetPos15(object); return; }
  if (object == (APTR)pos16) { SetPos16(object); return; }
  if (object == (APTR)pos17) { SetPos17(object); return; }
  if (object == (APTR)pos21) { SetPos21(object); return; }
  if (object == (APTR)pos22) { SetPos22(object); return; }
  if (object == (APTR)pos23) { SetPos23(object); return; }
  if (object == (APTR)pos24) { SetPos24(object); return; }
  if (object == (APTR)pos25) { SetPos25(object); return; }
  if (object == (APTR)pos26) { SetPos26(object); return; }
  if (object == (APTR)pos27) { SetPos27(object); return; }
  if (object == (APTR)Line1) { GoLine2(object); return; }
  if (object == (APTR)Line2) { GoLine3(object); return; }
  if (object == (APTR)Line3) { GoLine4(object); return; }
  if (object == (APTR)Line4) { GoLine5(object); return; }
  if (object == (APTR)Line5) { GoLine6(object); return; }
  if (object == (APTR)Line6) { GoLine7(object); return; }
  if (object == (APTR)Line7) { GoLine1(object); return; }
  if (object == (APTR)Print) { PrintLabels(object); return; }
  if (object == (APTR)pos18) { SetPos18(object); return; }
  if (object == (APTR)pos28) { SetPos28(object); return; }
  if (object == (APTR)pos31) { SetPos31(object); return; }
  if (object == (APTR)pos32) { SetPos32(object); return; }
  if (object == (APTR)pos33) { SetPos33(object); return; }
  if (object == (APTR)pos34) { SetPos34(object); return; }
  if (object == (APTR)pos35) { SetPos35(object); return; }
  if (object == (APTR)pos36) { SetPos36(object); return; }
  if (object == (APTR)pos37) { SetPos37(object); return; }
  if (object == (APTR)pos38) { SetPos38(object); return; }
  if (object == (APTR)Prev)  { PrevLabel(object); return; }
  if (object == (APTR)Next)  { NextLabel(object); return; }
  if (object == (APTR)Kill)  { KillLabel(object); return; }
}

/**************************************************************************/
/*>HandleMenu(USHORT firstcode)
   ----------------------------
   Menu handler to deal with multi-selection
   28.10.91 Original
   14.01.92 Added documentation for routine.
*/
HandleMenu(USHORT firstcode)
{
   struct MenuItem *item;
   USHORT nextcode = firstcode;
   while(nextcode != MENUNULL)
   {
      item = (struct MenuItem *)ItemAddress(Menu1, (long)nextcode);
      HandleEvent((APTR)item);
      nextcode = item->NextSelect;
   }
   return(0);
}
/**************************************************************************/
/*>OpenLibraries(void)
   -------------------
   Opens all required libraries
   28.10.91 Original
   14.09.92 Added documentation for routine.
*/
OpenLibraries(void)
{
   if ((IntuitionBase=(struct IntuitionBase *)
               OpenLibrary("intuition.library",INTUITION_REV)) == NULL)
               Die("Unable to open Intuition library");

   if ((GfxBase=(struct GfxBase *)
               OpenLibrary("graphics.library",GRAPHICS_REV)) == NULL)
               Die("Unable to open Graphics library");

   if ((IconBase=(struct Library *)
               OpenLibrary("icon.library",0)) == NULL)
               Die("Unable to open Icon library");

   AslBase=(struct Library *)OpenLibrary("asl.library",ASL_REV);
   /* We don't make any checks as AslBase isn't essential */

   return(0);
}

/**************************************************************************/
/*>OpenDisplay(void)
   -----------------
   Builds window, menus and gadgets. Opens window.
   28.10.91 Original
   17.01.92 Changed to use STSLib
   14.09.92 Added documentation for routine.
*/
OpenDisplay(void)
{
   struct NewWindow *nw;
   struct Screen    WBscrn;
   
   nw = BuildWindow(NULL,65,0,390,200,"PrLabel V1.2  SciTech Software 1992",
                    0,1);
   /* Modify the IDCMP flags of the basic NewWindow structure */
   nw->IDCMPFlags = IDCMP_GADGETUP | IDCMP_MENUPICK | IDCMP_CLOSEWINDOW;

   /* Find the size of the menu bar from the WorkBench */
   GetScreenData(&WBscrn,sizeof(struct Screen), WBENCHSCREEN, NULL);
   mb  = WBscrn.WBorTop + WBscrn.Font->ta_YSize + 1;

   /* Create gadgets */
   Line1 = BuildStringGadget(nw,Line1SIBuff,80,125,mb+5,  30,0,0,0,0);
   Line2 = BuildStringGadget(nw,Line2SIBuff,80,125,mb+20, 30,0,0,0,0);
   Line3 = BuildStringGadget(nw,Line3SIBuff,80,125,mb+35, 30,0,0,0,0);
   Line4 = BuildStringGadget(nw,Line4SIBuff,80,125,mb+50, 30,0,0,0,0);
   Line5 = BuildStringGadget(nw,Line5SIBuff,80,125,mb+65, 30,0,0,0,0);
   Line6 = BuildStringGadget(nw,Line6SIBuff,80,125,mb+80, 30,0,0,0,0);
   Line7 = BuildStringGadget(nw,Line7SIBuff,80,125,mb+95, 30,0,0,0,0);
   
   pos11 = BuildBoolGadget(nw," ",10,mb+5  ,1,1,0,0,0,1,0);
   pos12 = BuildBoolGadget(nw," ",10,mb+19 ,1,1,0,0,0,1,0);
   pos13 = BuildBoolGadget(nw," ",10,mb+33 ,1,1,0,0,0,1,0);
   pos14 = BuildBoolGadget(nw," ",10,mb+47 ,1,1,0,0,0,1,0);
   pos15 = BuildBoolGadget(nw," ",10,mb+61 ,1,1,0,0,0,1,0);
   pos16 = BuildBoolGadget(nw," ",10,mb+75 ,1,1,0,0,0,1,0);
   pos17 = BuildBoolGadget(nw," ",10,mb+89 ,1,1,0,0,0,1,0);
   if(SheetType == TWO_EIGHT || SheetType == THREE_EIGHT)
      pos18 = BuildBoolGadget(nw," ",10,mb+103,1,1,0,0,0,1,0);
   
   pos21 = BuildBoolGadget(nw," ",38,mb+5  ,1,1,0,0,0,1,0);
   pos22 = BuildBoolGadget(nw," ",38,mb+19 ,1,1,0,0,0,1,0);
   pos23 = BuildBoolGadget(nw," ",38,mb+33 ,1,1,0,0,0,1,0);
   pos24 = BuildBoolGadget(nw," ",38,mb+47 ,1,1,0,0,0,1,0);
   pos25 = BuildBoolGadget(nw," ",38,mb+61 ,1,1,0,0,0,1,0);
   pos26 = BuildBoolGadget(nw," ",38,mb+75 ,1,1,0,0,0,1,0);
   pos27 = BuildBoolGadget(nw," ",38,mb+89 ,1,1,0,0,0,1,0);
   if(SheetType == TWO_EIGHT || SheetType == THREE_EIGHT)
      pos28 = BuildBoolGadget(nw," ",38,mb+103,1,1,0,0,0,1,0);
   
   if(SheetType == THREE_EIGHT)
   {
      pos31 = BuildBoolGadget(nw," ",66,mb+5  ,1,1,0,0,0,1,0);
      pos32 = BuildBoolGadget(nw," ",66,mb+19 ,1,1,0,0,0,1,0);
      pos33 = BuildBoolGadget(nw," ",66,mb+33 ,1,1,0,0,0,1,0);
      pos34 = BuildBoolGadget(nw," ",66,mb+47 ,1,1,0,0,0,1,0);
      pos35 = BuildBoolGadget(nw," ",66,mb+61 ,1,1,0,0,0,1,0);
      pos36 = BuildBoolGadget(nw," ",66,mb+75 ,1,1,0,0,0,1,0);
      pos37 = BuildBoolGadget(nw," ",66,mb+89 ,1,1,0,0,0,1,0);
      pos38 = BuildBoolGadget(nw," ",66,mb+103,1,1,0,0,0,1,0);
   }
   
   Kill  = BuildBoolGadget(nw,"KILL",  230,mb+141,0,1,0,0,0,0,0);
   Next  = BuildBoolGadget(nw,"NEXT",  255,mb+125,0,1,0,0,0,0,0);
   Prev  = BuildBoolGadget(nw,"PREV",  202,mb+125,0,1,0,0,0,0,0);
   Print = BuildBoolGadget(nw,"PRINT!",11, mb+133,8,3,0,0,0,0,0);
   
   BuildFrame(nw,195,mb+118,120,44,0,0,1);
   
   /* Build Menus */
   Menu1     = BuildMenu(NULL,NULL,"Project");
   MenuItem1 = BuildMenuItem(NULL,0,(APTR)Menu1,"Open", 'O', 0,0,0,1);
   MenuItem2 = BuildMenuItem(NULL,0,(APTR)Menu1,"Save", 'S', 0,0,0,1);
   MenuItem3 = BuildMenuItem(NULL,0,(APTR)Menu1,"About",'\0',0,0,0,1);
   MenuItem4 = BuildMenuItem(NULL,0,(APTR)Menu1,"Quit", 'Q', 0,0,0,1);

   Window = (struct Window *)OpenWindow(nw);

   SetMenuStrip(Window, Menu1);

   return(0);
}

/**************************************************************************/
/*>Cleanup()
   ---------
   Routine required by STSLib
   17.01.91 Original
   14.09.92 Added documentation for routine.
*/
Cleanup()
{
   QuitProgram((APTR)0);

   return(0);
}

/**************************************************************************/
/*>QuitProgram(APTR object)
   ------------------------
   Closes the window and performs any other cleanup before exit.
   28.10.91 Original
   14.09.92 Added code to free STSLib stuff (oops!). Added documentation 
            for routine.
*/
QuitProgram(APTR object)
{
   if(Window) CloseWindow(Window);

   FreeSTSMenus(Menu1);
   FreeSTSGadgets(Line1);

   exit(0);
   
   return(0);
}

/**************************************************************************/
/*>ClearPrint(void)
   ----------------
   Sets all labels so that they are not printed.
   28.10.91 Original
   14.09.92 Added documentation for routine.
*/
ClearPrint(void)
{
   int j,
       k;
       
   for(j=0;j<3;j++)
      for(k=0;k<8;k++)
         label[j][k].print = 0;
         
   return(0);
}

/**************************************************************************/
/*>Usage(void)
   -----------
   Displays a usage message.
   28.10.91 Original
   14.09.92 Added documentation for routine.
*/
Usage(void)
{
   OpenIO();
   
   printf("PrLabel V1.2 Copyright SciTech Software, 1992\n");
   printf("This program is freely distributable shareware (fee £5.00) \
providing all files\n");
   printf("are unaltered and distributed together. Only a nominal charge \
may be made for\n");
   printf("distribution.\n");
   printf("Usage: PrLabel [-27][-28][-38][-s<c>]\n");
   printf("       Prints text for address labels, etc.\n");
   printf("       Flags -27,-28,-38 select the label layout (default: 3x8)\n");
   printf("       Flag  -s followed by a character for record delimiter \
(default: ,)\n\n");

   exit(0);
   return(0);
}

/**************************************************************************/
/*>OpenIO(void)
   ------------
   Opens the console for default C Level 2 I/O. This is normally done by
   the Lattice _main() code, but we link with tinymain.o which does not
   include this.
   28.10.91 Original
   14.09.92 Added documentation for routine.
*/
#include <ios1.h>
#include <fcntl.h>
extern struct UFB _ufbs[];
extern int _fmode,_iomode;

OpenIO(void)
{
   register int x;

        _ufbs[0].ufbfh = Input();
        _ufbs[1].ufbfh = Output();
        _ufbs[2].ufbfh = Open("*", MODE_OLDFILE);
        x = UFB_NC;                     /* do not close CLI defaults    */

   _ufbs[0].ufbflg |= UFB_RA | O_RAW | x;
   _ufbs[1].ufbflg |= UFB_WA | O_RAW | x;
   _ufbs[2].ufbflg |= UFB_RA | UFB_WA | O_RAW;

   x = (_fmode) ? 0 : _IOXLAT;
   stdin->_file = 0;
   stdin->_flag = _IOREAD | x;   
   stdout->_file = 1;
   stdout->_flag = _IOWRT | x;
   stderr->_file = 2;
   stderr->_flag = _IORW | x;

   return(0);
}
