/***************************************************************************
 *                                                                         *
 *  Filename : TeXFormat.c                                                 *
 *                                                                         *
 *  Description : A front-end for the PasTeX TeX implementation.           *
 *                The program looks for the format files found in the path *
 *                TeX:Formats and enables the user to switch between the   *
 *                available format files via a gadtools interface.         *
 *                                                                         *
 *  Return Codes :  10 - No format files available.                        *
 *                  20 - Couldn't open window.                             *
 *                  25 - Couldn't get visualinfo of the public screen.     *
 *                  30 - Couldn't create gadget context.                   *
 *                  40 - Couldn't create gadtools gadgets.                 *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *                         Modification History                            *
 *                                                                         *
 *  Date      Author       Comments                                        *
 * ----------------------------------------------------------------------  *
 *  9.3.92    R.Bödi       Created.                                        *
 *  8.6.92    R.Bödi       Fixed bug (first format entry couldn't be       *
 *                         selected.)                                      *
 * 12.9.93    R.Bödi       Added parameters for CLI and WB.                *
 * 14.9.93    R.Bödi       Added 'Save' button.                            *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 * Copyright © 1992 Richard Bödi,  All rights reserved.                    *
 *                                                                         *
 ***************************************************************************/

/*----------------------------- INCLUDES ----------------------------------*/

#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "dos.h"

#define INTUITION_IOBSOLETE_H

#include "dos/dosasl.h"
#include "graphics/displayinfo.h"
#include "intuition/intuition.h"
#include "intuition/screens.h"
#include "intuition/gadgetclass.h"
#include "libraries/gadtools.h"
#include "workbench/workbench.h"
#include "workbench/startup.h"
#include "utility/tagitem.h"

#include "clib/exec_protos.h"
#include "clib/dos_protos.h"
#include "clib/graphics_protos.h"
#include "clib/intuition_protos.h"
#include "clib/gadtools_protos.h"
#include "clib/wb_protos.h"
#include "clib/icon_protos.h"
#include "clib/utility_protos.h"

#include "pragmas/exec_pragmas.h"
#include "pragmas/dos_pragmas.h"
#include "pragmas/graphics_pragmas.h"
#include "pragmas/intuition_pragmas.h"
#include "pragmas/gadtools_pragmas.h"
#include "pragmas/wb_pragmas.h"
#include "pragmas/icon_pragmas.h"
#include "pragmas/utility_pragmas.h"


/*--------------------------- DEFINES -------------------------------------*/

#define  VERSION        " V2.00 "

#define  COMMENTLENGTH         82
#define  CMDSTRLENGTH         512

#define  ID_FORMAT_SEL          1
#define  ID_SAVE                2
#define  ID_OK                  3

#define  max(a,b)    ((a) > (b) ? (a) : (b))

/*-------------------- STRUCTURE DEFINITIONS ------------------------------*/

enum ScanError  { SCAN_OK, NO_LOCK, NO_FORMAT, NO_ENV, NO_MATCH, NO_MEMORY };
enum Keywords   { KW_PUBSCREEN, KW_CURRENTFORMAT, KW_FORMATPATH, KW_PATTERN, LAST_KW };
enum ErrorIDs   { ERR_NOERROR, ERR_FORMATFILES = 10, ERR_OPENWINDOW = 20,
                  ERR_NOVISUALINFO = 25, ERR_GADGETCONTEXT = 30, ERR_NOGADTOOLS = 40 };

struct FormatNode
   {
   struct FormatNode   *NextNode;
   char                 Name[FNSIZE];
   char                 Comment[COMMENTLENGTH];
   int                  ID;
   };

struct TeXFormat
   {
   struct FormatNode   *FirstNode;
   char               **FormatArray;
   struct FormatNode   *CurrentFormat;
   int                  NoOfFormats;
   int                  MaxNameLength;
   int                  MaxCommentLength;
   };

struct Settings
   {
   long     ArgPtr[LAST_KW];
   char     ArgStr[LAST_KW][FMSIZE];              // FMSIZE see file dos.h
   char     CurrentFormat[FNSIZE];
   };

/*--------------------- FUNCTION PROTOTYPES -------------------------------*/

void              ParseShell (int, char **, struct Settings *);
void              ParseWB (struct WBStartup *, struct Settings *);
enum ScanError    ScanFormatPath (struct TeXFormat *, struct Settings *);
void              SetWindowLimits (struct TeXFormat *, enum ScanError);
BOOL              PrepareGadgets (struct TeXFormat *);
void              DrawGraphics (enum ScanError, struct Settings *, struct TeXFormat *);
void              HandleIDCMP (struct TeXFormat *, struct Settings *);
void              Cleanup (char *, enum ErrorIDs);


/*------------------------ EXTERNAL VARIABLES ----------------------------*/

extern struct Library         *SysBase;
extern struct DOSBase         *DOSBase;
extern struct GfxBase         *GfxBase;
extern struct IntuitionBase   *IntuitionBase;
extern struct GadToolsBase    *GadToolsBase;
extern struct WorkbenchBase   *WorkbenchBase;
extern struct IconBase        *IconBase;
extern struct UtilityBase     *UtilityBase;


/*-------------------------- GLOBAL DATA ----------------------------------*/

char  Version[]   = "$VER: TeXFormat  Release " VERSION " (" __DATE__ ")         © R.Bödi";
char  Title[]     = "TeXFormat " VERSION "   © R.Bödi";
char  *Keywords[] = { "PUBSCREEN", "CURRENTFORMAT", "FORMATPATH", "PATTERN" };
char  *Switchs[]  = { "/K", "/K", "/K", "/K" };

struct Screen  *PubScreen;
struct Window  *Window = NULL;
struct Gadget  *ContextGad = NULL;
void           *VisInfo = NULL;

UWORD           WinWidth, WinHeight;

STRPTR          ErrorMsg[] = { "",
                               "Couldn't find directory",
                               "Couldn't find a TeX format file in ",
                               "Environment variable unset",
                               "Couldn't find TeX format file defined by the environment variable",
                               "Not enough memory available" };

struct TagItem    Window_TagList[] =
        { { WA_Left, 100 },
          { WA_Top, 100 },
          { WA_Width, 30 },
          { WA_Height, 30 },
          { WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_GADGETUP | IDCMP_IDCMPUPDATE | IDCMP_MENUPICK |
                      MXIDCMP | CHECKBOXIDCMP | INTEGERIDCMP | BUTTONIDCMP },
          { WA_Flags, WFLG_CLOSEGADGET | WFLG_DRAGBAR | WFLG_SMART_REFRESH | WFLG_ACTIVATE },
          { WA_Title, (ULONG)Title },
          { WA_PubScreenName, NULL },
          { WA_PubScreenFallBack, TRUE },
          { WA_MaxHeight, 400 },
          { WA_MaxWidth, 500 },
          { TAG_END, NULL } };

struct TagItem
   Visual_TagList[] = { { TAG_END, NULL } };

struct EasyStruct
   AboutReq   = { sizeof (struct EasyStruct), 0, "About",
                  "\n            TeXFormat %s         \n\n     A Format File Selector for TeX \n\n        (c) 1993 by Richard Bödi\n\n Mathematisches Institut\n Universität Tübingen\n Auf der Morgenstelle 10\n 72076 Tübingen\n Germany\n\ne-mail :\n mmisa01@mailserv.zdv.uni-tuebingen.de\n",
                  "OK" };

struct NewGadget
   NG_FormatSel   = { 24, 44, 120, 27, NULL, NULL, ID_FORMAT_SEL,
                      PLACETEXT_RIGHT, NULL, NULL },

   NG_Save        = { 0, 0, 60, 16, "Save", NULL, ID_SAVE,
                      PLACETEXT_IN, NULL, NULL },

   NG_OK          = { 0, 0, 60, 16, "OK", NULL, ID_OK,
                      PLACETEXT_IN, NULL, NULL };

struct IntuiText
   Path_Text      = { 1, 0, JAM2, 35, 40, NULL, NULL, NULL },
   NoFormat_Text  = { 1, 0, JAM2, 35, 25, NULL, NULL, &Path_Text },
   Descript_Text  = { 1, 0, JAM2, 0, 27, NULL, "Description", NULL },
   FormatSel_Text = { 1, 0, JAM2, 48, 27, NULL, "TeX Format ", &Descript_Text },
   Comment_Text   = { 1, 0, JAM2, 0, 35, NULL, NULL, NULL };


struct NewMenu NewMenu[] = { NM_TITLE, "File", NULL, 0, 0, NULL,
                             NM_ITEM, "About",   NULL, 0, 0, NULL,
                             NM_ITEM, NM_BARLABEL,  NULL, 0, 0, NULL,
                             NM_ITEM, "Quit",    "Q",  0, 0, NULL,
                             NM_END };

struct Menu   *Menu = NULL;


/*------------------------------- CODE ------------------------------------*/

main (int argc, char *argv[])

{
struct TeXFormat  TeXFormat;
struct Settings   Settings;
enum ScanError    FormatAvail;
struct TagItem   *Tag = NULL;


if (argc == 0) ParseWB ((struct WBStartup *)argv, &Settings);
if (argc > 1)  ParseShell (argc, argv, &Settings);

FormatAvail   = ScanFormatPath (&TeXFormat, &Settings);
Tag           = FindTagItem (WA_PubScreenName, Window_TagList);
Tag->ti_Data  = (ULONG)Settings.ArgStr[KW_PUBSCREEN];

if (Window = OpenWindowTagList (NULL, Window_TagList))
   {
   PubScreen = Window->WScreen;
   SetWindowLimits (&TeXFormat, FormatAvail);
   Delay (25);

   if (VisInfo = GetVisualInfoA (PubScreen, Visual_TagList))
      {
      if (Menu = CreateMenus (NewMenu, TAG_DONE))
         if (LayoutMenus (Menu, VisInfo, TAG_DONE))
            SetMenuStrip (Window, Menu);

      if (CreateContext (&ContextGad))
         {
         if (FormatAvail == SCAN_OK)
            {
            if (PrepareGadgets (&TeXFormat))
               {
               DrawGraphics (FormatAvail, &Settings, &TeXFormat);
               HandleIDCMP (&TeXFormat, &Settings);
               Cleanup (NULL, ERR_NOERROR);
               }
            else
               Cleanup ("Couldn't create gadtools gadgets.\n", ERR_NOGADTOOLS);
            }
         else
            {
            DrawGraphics (FormatAvail, &Settings, &TeXFormat);
            HandleIDCMP (&TeXFormat, &Settings);
            Cleanup (NULL, ERR_FORMATFILES);
            }
         }
      else
         Cleanup ("Couldn't create gadget context.\n", ERR_GADGETCONTEXT);
      }
   else
      Cleanup ("Couldn't get visualinfo of the public screen.\n", ERR_NOVISUALINFO);
   }
else
   Cleanup ("Couldn't open window.\n", ERR_OPENWINDOW);
}


/***************************************************************************
 *                                                                         *
 *  Function name : ParseWB                                                *
 *                                                                         *
 *  Description : Fetches and parses the ToolTypes from the TeXFormat icon.*
 *                Allowed tooltypes are :                                  *
 *                   PUBSCREEN (Specifies the public screen on which the   *
 *                              program's window should open.              *
 *                   CURRENTFORMAT (Specifies the name of the environment  *
 *                                  variable in which the name of the      *
 *                                  current TeX format file is stored.)    *
 *                   FORMATPATH (Specifies the path for the TeX            *
 *                               format files is stored.)                  *
 *                   PATTERN (Specifies the file pattern for fromat files. *
 *                            Typically it's #?.fmt.)                      *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *  Synopsis : ParseWB (WBArgStr, Settings)                                *
 *                                                                         *
 *  Parameters :                                                           *
 *    (struct WBStartup **) WBArgStr:                                      *
 *          The WB argument string.                                        *
 *    (struct Settings *) Settings:                                        *
 *          The tags of theses structure are filled by this procedure.     *
 *                                                                         *
 *  Return value : None                                                    *
 *                                                                         *
 ***************************************************************************/

void  ParseWB (struct WBStartup *WBArgStr, struct Settings *Settings)

{
struct DiskObject   *DiskObj;
struct WBArg        *WBArg;
char               **ToolArray;


WBArg = WBArgStr->sm_ArgList;

if (WBArg->wa_Name)     // get tooltypes
   if (DiskObj = GetDiskObject (WBArg->wa_Name))
      {
      ToolArray = (char **)DiskObj->do_ToolTypes;
      stpcpy (Settings->ArgStr[KW_PUBSCREEN], FindToolType (ToolArray, Keywords[KW_PUBSCREEN]));
      stpcpy (Settings->ArgStr[KW_CURRENTFORMAT], FindToolType (ToolArray, Keywords[KW_CURRENTFORMAT]));
      stpcpy (Settings->ArgStr[KW_FORMATPATH], FindToolType (ToolArray, Keywords[KW_FORMATPATH]));
      stpcpy (Settings->ArgStr[KW_PATTERN], FindToolType (ToolArray, Keywords[KW_PATTERN]));
      FreeDiskObject (DiskObj);
      }

GetVar (Settings->ArgStr[KW_CURRENTFORMAT], Settings->CurrentFormat, sizeof (Settings->CurrentFormat), GVF_GLOBAL_ONLY);
}



/***************************************************************************
 *                                                                         *
 *  Function name : ParseShell                                             *
 *                                                                         *
 *  Description : Parses the commandline for parameters.                   *
 *                Allowed parameters are :                                 *
 *                   PUBSCREEN\K (Specifies the public screen on which the *
 *                                program's window should open.            *
 *                   CURRENTFORMAT/K (Specifies the name of the environment*
 *                                    variable in which the name of the    *
 *                                    current TeX format file is stored.   *
 *                   FORMATPATH/K (Specifies the the path for the TeX      *
 *                                 format files is stored.                 *
 *                   PATTERN(K (Specifies the file pattern for fromat files*
 *                              Typically it's #?.fmt.)                    *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *  Synopsis : ParseShell (NoOfArgs, Arg, Settings)                        *
 *                                                                         *
 *  Parameters :                                                           *
 *    (int) NoOfArgs:                                                      *
 *          The number of arguments.                                       *
 *    (char **) Arg:                                                       *
 *          The shell argument string.                                     *
 *    (struct Settings *) Settings:                                        *
 *          The tags of theses structure are filled by this procedure.     *
 *                                                                         *
 *  Return value : None                                                    *
 *                                                                         *
 ***************************************************************************/

void  ParseShell (int NoOfArgs, char **Arg, struct Settings *Settings)

{
int            kword;
struct RDArgs *RDArgs;
char           Template[CMDSTRLENGTH];


for (kword = 0, Template[0] = 0; kword < LAST_KW; kword++)
   {
   if (Template[0]) strcat (Template, ",");
   strcat (Template, Keywords[kword]);
   strcat (Template, Switchs[kword]);
   }

if (RDArgs = ReadArgs (Template, Settings->ArgPtr, NULL))
   {
   for (kword = 0; kword < LAST_KW; kword++)
      if (Settings->ArgPtr[kword])
         stpcpy (Settings->ArgStr[kword], (char *)Settings->ArgPtr[kword]);
   }
else
   PrintFault (IoErr (), "Error reading arguments");

GetVar (Settings->ArgStr[KW_CURRENTFORMAT], Settings->CurrentFormat, sizeof (Settings->CurrentFormat), GVF_GLOBAL_ONLY);

FreeArgs (RDArgs);
}


/***************************************************************************
 *                                                                         *
 *  Function name : ScanFormatPath                                         *
 *                                                                         *
 *  Description : Scans the format path for TeX format files, creates      *
 *                and fills for each file a struct FormatNode, updates     *
 *                the TeXFormat structure and reads the Settings->Texformat*
 *                environment variable.                                    *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *  Synopsis : ScanFormatPath (TeXFormat, Settings)                        *
 *                                                                         *
 *  Parameters :                                                           *
 *    (struct TeXFormat *) TeXFormat:                                      *
 *          This structure will be filled with the names of the format     *
 *          files found.                                                   *
 *    (struct Settings *) Settings:                                        *
 *          Contains the path and extension of the format files and the    *
 *          name of the TEXFORMAT environment variable.                    *
 *                                                                         *
 *  Return value : (enum ScanError)                                        *
 *    SCAN_OK, if at least one TeX format file was found and the content   *
 *             this variable matches a scanned TeX format file.            *
 *    NO_LOCK, if path couldn't be locked for examination.                 *
 *  NO_FORMAT, if no TeX format file was found.                            *
 *     NO_ENV, if one of the environment variables is unset.               *
 *   NO_MATCH, if content of the CURRENTFORMAT environment variable        *
 *             matches no scanned format file.                             *
 *  NO_MEMORY, if no memory for the FormatNodes was available.             *
 *                                                                         *
 ***************************************************************************/

enum ScanError    ScanFormatPath (struct TeXFormat *TeXFormat, struct Settings *Settings)

{
int                  Index;
BPTR                 OldLock, NewLock;
BOOL                 ActFormatFound = FALSE, Match, Error = FALSE;
struct AnchorPath    APath;
struct FormatNode   *NewNode, *LastNode = NULL;
char                 FormatName[FNSIZE];


APath.ap_BreakBits          = 0;
APath.ap_Strlen             = 0;
TeXFormat->FirstNode        = NULL;

if ((strlen (Settings->CurrentFormat) != 0) && (strlen (Settings->ArgStr[KW_FORMATPATH]) != 0))
   {
   if (NewLock = Lock (Settings->ArgStr[KW_FORMATPATH], ACCESS_READ))
      {
      OldLock = CurrentDir (NewLock);

      for (Index = 0, Match = MatchFirst (Settings->ArgStr[KW_PATTERN], &APath); !Match; Match = MatchNext (&APath), Index++)
         {
         SplitName (APath.ap_Info.fib_FileName, '.', FormatName, 0, sizeof (FormatName));
         if (strlen (FormatName) == 0) Index--;
         else
            {
            if (NewNode = (struct FormatNode *) calloc (sizeof (struct FormatNode), 1))
               {
               if (TeXFormat->FirstNode == NULL) TeXFormat->FirstNode = NewNode;
               else                              LastNode->NextNode   = NewNode;

               sprintf (NewNode->Name, "%-s", FormatName);
               stpcpy (NewNode->Comment, APath.ap_Info.fib_Comment);
               LastNode = NewNode;

               if (!strcmpi (Settings->CurrentFormat, FormatName))
                  {
                  TeXFormat->CurrentFormat  = NewNode;
                  ActFormatFound            = TRUE;
                  }
               }
            else
               {
               Error = TRUE;
               break;
               }
            }
         }

      MatchEnd (&APath);
      CurrentDir (OldLock);
      UnLock (NewLock);

      TeXFormat->NoOfFormats  = Index;

      if (Error)                    return (NO_MEMORY);
      if (!TeXFormat->NoOfFormats)  return (NO_FORMAT);
      if (!ActFormatFound)          return (NO_MATCH);

      TeXFormat->FormatArray  = (char **)calloc (TeXFormat->NoOfFormats + 1, sizeof (TeXFormat->FormatArray[0]));

      if (TeXFormat->FormatArray)
         {
         for (Index = 0, NewNode = TeXFormat->FirstNode; Index < TeXFormat->NoOfFormats; Index++, NewNode = NewNode->NextNode)
            TeXFormat->FormatArray[Index]  = NewNode->Name;

         strsrt (TeXFormat->FormatArray, TeXFormat->NoOfFormats);
         TeXFormat->FormatArray[TeXFormat->NoOfFormats]  = NULL;

         for (NewNode = TeXFormat->FirstNode; NewNode != NULL; NewNode = NewNode->NextNode)
            for (Index = 0; Index < TeXFormat->NoOfFormats; Index++)
               if (TeXFormat->FormatArray[Index] == NewNode->Name)
                  NewNode->ID = Index;
         }
      else
         return (NO_MEMORY);
      }
   else
      return (NO_LOCK);
   }
else
   return (NO_ENV);

return (SCAN_OK);
}



/***************************************************************************
 *                                                                         *
 *  Function name : SetWindowLimits                                        *
 *                                                                         *
 *  Description : Sets the size of the window corresponding to the number  *
 *                and length of the TeX format file entries.               *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *  Synopsis : SetWindowLimits (TeXFormat, Mode)                           *
 *                                                                         *
 *  Parameters :                                                           *
 *    (struct TeXFormat *) TeXFormat:                                      *
 *          This structure contains the names of the TeX formats available.*
 *    (enum ScanError) Mode                                                *
 *       Specifies whether or not a format file was                        *
 *       found in the format path.                                         *
 *                                                                         *
 *  Return value : None                                                    *
 *                                                                         *
 ***************************************************************************/

void SetWindowLimits (struct TeXFormat *TeXFormat, enum ScanError Mode)

{
struct IntuiText     LongestString;
struct FormatNode   *Node;
int                  MaxLen;

const   WidthOffset = 70, HeightOffset = 75, GroupSpacing = 10;


switch (Mode)
   {
   case SCAN_OK:
      LongestString.IText         = FormatSel_Text.IText;
      TeXFormat->MaxNameLength    = IntuiTextLength (&LongestString);
      LongestString.IText         = Descript_Text.IText;
      TeXFormat->MaxCommentLength = IntuiTextLength (&LongestString);

      for (Node = TeXFormat->FirstNode; Node != NULL; Node = Node->NextNode)
         {
         LongestString.IText = Node->Name;
         if (IntuiTextLength (&LongestString) > TeXFormat->MaxNameLength)
            TeXFormat->MaxNameLength = IntuiTextLength (&LongestString);

         LongestString.IText = Node->Comment;
         if (IntuiTextLength (&LongestString) > TeXFormat->MaxCommentLength)
            TeXFormat->MaxCommentLength = IntuiTextLength (&LongestString);
         }

      TeXFormat->MaxNameLength    += GroupSpacing;
      TeXFormat->MaxCommentLength += GroupSpacing;
      MaxLen = TeXFormat->MaxNameLength + TeXFormat->MaxCommentLength;
      break;

   default:
      LongestString.IText = ErrorMsg[Mode];
      MaxLen = IntuiTextLength (&LongestString);
      TeXFormat->NoOfFormats = 0;
      break;
   }

LongestString.ITextFont = PubScreen->Font;

WinWidth  = MaxLen + WidthOffset;
WinHeight = (PubScreen->Font->ta_YSize + 2) * TeXFormat->NoOfFormats + HeightOffset;

SizeWindow (Window, WinWidth - Window->Width, WinHeight - Window->Height);
}


/***************************************************************************
 *                                                                         *
 *  Function name : PrepareGadgets                                         *
 *                                                                         *
 *  Description : Adds all gadgets to the window.                          *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *  Synopsis : PrepareGadgets (TeXFormat)                                  *
 *                                                                         *
 *  Parameters :                                                           *
 *    (struct TeXFormat *) TeXFormat:                                      *
 *          This structure contains the names of the TeX formats available.*
 *                                                                         *
 *  Return value : (BOOL)                                                  *
 *       TRUE,  if creation of gadget succeeded.                           *
 *      FALSE,  otherwise.                                                 *
 *                                                                         *
 ***************************************************************************/

BOOL PrepareGadgets (struct TeXFormat *TeXFormat)

{
struct Gadget       *NextGadget;


NextGadget = ContextGad;

NG_FormatSel.ng_VisualInfo    = VisInfo;
NG_Save.ng_VisualInfo         = VisInfo;
NG_OK.ng_VisualInfo           = VisInfo;

NG_FormatSel.ng_TextAttr      = PubScreen->Font;
NG_Save.ng_TextAttr           = PubScreen->Font;
NG_OK.ng_TextAttr             = PubScreen->Font;

NG_OK.ng_LeftEdge    = WinWidth -  NG_OK.ng_Width  - 15;
NG_OK.ng_TopEdge     = WinHeight - NG_OK.ng_Height -  8;
NG_Save.ng_LeftEdge  = 15;
NG_Save.ng_TopEdge   = NG_OK.ng_TopEdge;

NextGadget = CreateGadget (MX_KIND, NextGadget, &NG_FormatSel,
                           GTMX_Labels, (ULONG)TeXFormat->FormatArray,
                           GTMX_Spacing, 2,
                           GTMX_Active, TeXFormat->CurrentFormat->ID,
                           TAG_END);

NextGadget = CreateGadget (BUTTON_KIND, NextGadget, &NG_Save, TAG_END);
NextGadget = CreateGadget (BUTTON_KIND, NextGadget, &NG_OK, TAG_END);

if (NextGadget)
   {
   AddGList (Window, ContextGad, 0, -1, NULL);
   RefreshGadgets (ContextGad, Window, NULL);
   GT_RefreshWindow (Window, NULL);
   return (TRUE);
   }
else
   return (FALSE);
}


/***************************************************************************
 *                                                                         *
 *  Function name : DrawGraphics                                           *
 *                                                                         *
 *  Description : Adds all additional graphics on the window.              *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *  Synopsis : DrawGraphics (Mode, Settings, TeXFormat)                    *
 *                                                                         *
 *  Parameters :                                                           *
 *    (enum ScanError) Mode                                                *
 *       Specifies whether or not a format file was                        *
 *       found in the format path.                                         *
 *    (struct Settings *) Settings:                                        *
 *          Contains the path and extension of the format files and the    *
 *          name of the TEXFORMAT environment variable.                    *
 *    (struct TeXFormat *) TeXFormat:                                      *
 *          This structure contains the names of the TeX formats available.*
 *                                                                         *
 *  Return value : None                                                    *
 *                                                                         *
 ***************************************************************************/

void DrawGraphics (enum ScanError Mode, struct Settings *Settings, struct TeXFormat *TeXFormat)

{
struct FormatNode   *FNode;

const    DeltaX = 15, DeltaY = 28, YOffset = 39, VSpacing = 10;


switch (Mode)
   {
   case SCAN_OK:
      DrawBevelBox (Window->RPort, DeltaX, YOffset, WinWidth - (DeltaX << 1), WinHeight - DeltaY - YOffset,
                    GT_VisualInfo, (ULONG)VisInfo,
                    GTBB_Recessed, TRUE,
                    TAG_END);
      Descript_Text.LeftEdge = FormatSel_Text.LeftEdge + max (TeXFormat->MaxNameLength, IntuiTextLength (&Descript_Text));
      PrintIText (Window->RPort, &FormatSel_Text, 0, 0);

      Comment_Text.LeftEdge  = Descript_Text.LeftEdge;

      for (FNode = TeXFormat->FirstNode; FNode != NULL; FNode = FNode->NextNode)
         {
         Comment_Text.TopEdge += VSpacing;
         Comment_Text.IText    = FNode->Comment;
         PrintIText (Window->RPort, &Comment_Text, 0, 0);
         }
      break;

   default:
      NoFormat_Text.IText = ErrorMsg[Mode];
      if (Mode != NO_ENV) Path_Text.IText = Settings->ArgStr[KW_FORMATPATH];
      else Path_Text.IText = NULL;
      PrintIText (Window->RPort, &NoFormat_Text, 0, 0);
      break;
   }
}


/***************************************************************************
 *                                                                         *
 *  Function name : HandleIDCMP                                            *
 *                                                                         *
 *  Description : Tests IDCMP port for incoming messages.                  *
 *                This function returns if the window close gaget or the   *
 *                CANCEL gadget was activated.                             *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *  Synopsis : HandleIDCMP (TeXFormat, Settings)                           *
 *                                                                         *
 *  Parameters :                                                           *
 *    (struct TeXFormat *) TeXFormat:                                      *
 *          This structure contains the names of the TeX formats available.*
 *    (struct Settings *) Settings:                                        *
 *          Contains the path and extension of the format files and the    *
 *          name of the TEXFORMAT environment variable.                    *
 *                                                                         *
 *  Return value : None                                                    *
 *                                                                         *
 ***************************************************************************/

void HandleIDCMP (struct TeXFormat *TeXFormat, struct Settings *Settings)

{
struct FormatNode   *FNode;
struct IntuiMessage *Msg;
struct Gadget       *Gadget;
ULONG                IClass, IDCMPFlag = NULL;
UWORD                Code;
USHORT               MenuItem;
int                  GadID;
char                 CMDStrg[128];
BOOL                 Exit = FALSE;


while (!Exit)
   {
   if(!(Msg = GT_GetIMsg (Window->UserPort)))
      {
      WaitPort (Window->UserPort);
      continue;
      }

   IClass = Msg->Class;
   Code   = Msg->Code;
   GT_ReplyIMsg (Msg);

   switch (IClass)
      {
      case IDCMP_GADGETUP:
      case IDCMP_GADGETDOWN:
         Gadget = (struct Gadget *) Msg->IAddress;
         GadID  = Gadget->GadgetID;

         switch (GadID)
            {
            case ID_FORMAT_SEL:
               for (FNode = TeXFormat->FirstNode; FNode != NULL; FNode = FNode->NextNode)
                  if (FNode->ID == Code) break;
               TeXFormat->CurrentFormat = FNode;
               SetVar (Settings->ArgStr[KW_CURRENTFORMAT], FNode->Name, strlen (FNode->Name), GVF_GLOBAL_ONLY);
               break;

            case ID_SAVE:
               sprintf (CMDStrg, "copy env:%s envarc:%s", Settings->ArgStr[KW_CURRENTFORMAT], Settings->ArgStr[KW_CURRENTFORMAT]);
               system (CMDStrg);
               break;

            case ID_OK:
               Exit = TRUE;
               break;
            }
         break;

      case IDCMP_MENUPICK:
         MenuItem = ITEMNUM (Code);
         switch (MenuItem)
            {
            case 0:
               EasyRequest (Window, &AboutReq, &IDCMPFlag, VERSION);
               break;
            case 2:
               Exit = TRUE;
               break;
            }
         break;

      case IDCMP_CLOSEWINDOW:
         Exit = TRUE;
         break;
      }
   }
}


/***************************************************************************
 *                                                                         *
 *  Function name : Cleanup                                                *
 *                                                                         *
 *  Description : Frees all allocated memory, closes all used libraries,   *
 *                closes all screens and windows.                          *
 *                Possibly prints some error message and exits.            *
 *                                                                         *
 ***************************************************************************
 *                                                                         *
 *  Synopsis : Cleanup (Strg, ErrorID)                                     *
 *                                                                         *
 *  Parameters :                                                           *
 *    (char *) Strg:                                                       *
 *       Pointer to a message string.                                      *
 *    (enum ErrorIDs) ErrorID:                                             *
 *       Error code identifier.                                            *
 *                                                                         *
 ***************************************************************************/

void Cleanup (char *Strg, enum ErrorIDs ErrorID)

{
if (Strg) puts (Strg);

if (Menu)
   {
   if (Window) ClearMenuStrip (Window);
   FreeMenus (Menu);
   }

if (Window)        CloseWindow (Window);
if (ContextGad)    FreeGadgets (ContextGad);
if (VisInfo)       FreeVisualInfo (VisInfo);

exit (ErrorID);
}

