/******************************************************************************
** Sub.c
*******************************************************************************
**
** description:
**
** This file contains some subroutines for GALer.
**
******************************************************************************/
 





/********************************* includes **********************************/
 
#include <libraries/mui.h>

#include <dos/dostags.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <devices/timer.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/reqtools.h>
#include <libraries/locale.h>
#include <intuition/intuition.h>

#include <proto/locale.h>
#include <proto/reqtools.h>
#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/muimaster.h>

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "GALer.h"
#include "Localize.h"





/********************************** defines **********************************/

#define YES_GADID         1
#define NO_GADID          2
#define OK_GADID         10
#define CONT_GADID       11
#define CANCEL_GADID     12


#define MAKEJED_ID        1             /* gadget IDs for assembler options */
#define MAKEFUSE_ID       2
#define MAKECHIP_ID       3
#define MAKEPIN_ID        4
#define AUTOSAVE_ID       5
#define ADJUSTGAL_ID      6


#define PROG_EMPTY_ID     1             /* gadget IDs for write access */
#define PROG_VERIFY_ID    2
#define COPY_EMPTY_ID     3
#define COPY_VERIFY_ID    4
#define ERASE_EMPTY_ID    5


#define JEDSEC_ID         1             /* gadget IDs for JEDEC parameter */
#define JEDFUSE_ID        2
#define JEDFILE_ID        3


#define EDITORSTRING_ID   1             /* gadget IDs for editor selection */


#define MAX_NUM_OF_LINES 20





/******************************** functions **********************************/






/******************************** variables **********************************/
 
extern  struct  AppString { LONG   as_ID;
                            STRPTR as_Str;
                          };

extern  struct  AppString   AppStrings[];


extern  struct  Catalog     *catalog;

extern  struct  timerequest *timereq;

extern  struct  rtFileRequester *filereq;

extern  int     GALType, MaxFuseAdr, RowSize, XORSize, SigAdr;
extern  int     hw_version;

extern  APTR    app, main_win, LV_text;

extern  UBYTE   main_win_title[];
 
                                                /* defaults: */

struct  Configuration Config = { GAL16V8,       /*GAL16V8*/
                                 YES,           /*Requester für Typ*/
                                 YES,           /*Jedec erzeugen*/
                                 NO,            /*kein Fuse-File*/
                                 NO,            /*kein Chip-File*/
                                 NO,            /*kein Pin-File*/
                                 NO,            /*kein Auto-Save*/
                                 YES,           /*autom. GALTyp einstellen*/
                                 YES,           /*Leertest vor GAL-Prog.*/
                                 YES,           /*Verify nach GAL-Prog.*/
                                 YES,           /*Leertest vor Copy-GAL*/
                                 YES,           /*Verify nach Copy-GAL*/
                                 YES,           /*Leertest nach GAL-Löschen*/
                                 NO,            /*Sec.Bit der Jedec-Datei*/
                                 YES,           /*Fuse-Checksumme der Jedec*/
                                 NO,            /*File-Checksumme der Jedec*/
                                 HW_GALER_1_3,  /*Hardware-Version*/
                                 "run c:ed \"%s\""
                               };


struct  Configuration DummyConfig;              /* dummy for LoadConfig */


UBYTE   ErrorLineStr[22];


char    filename[108];                          /* buffer for filename   */
char    path[108 + 130 + 4];                    /* buffer for directory, */
                                                /* filename and suffix   */

char    prevSourceFile[108 + 130 + 4];          /* name of the prev. */
                                                /* assembled file */

char    *cmps[4];







/******************************************************************************
** Schreibverhalten()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: opens a preferences window in which can be selected whether or
**          not a programmed GAL should be verified or an empty test should
**          be done before writing to a GAL
**
******************************************************************************/
 
void Schreibverhalten(void)
{
    int   open, done;

    ULONG id, signals;

    APTR  win;
    APTR  prog_empty, prog_verify, copy_empty, copy_verify, erase_empty;
    APTR  ok;




    set(app, MUIA_Application_Sleep, TRUE);     /* deactivate application */


                                                /* make window object */
    win = WindowObject,
        MUIA_Window_Title, AppStrings[MSG_WRITEACC_WIN].as_Str,
        MUIA_Window_CloseGadget, FALSE,
        MUIA_Window_NoMenus, TRUE,
        MUIA_HelpNode, "MenWriteAcc",

            WindowContents, VGroup,
                Child, HGroup, GroupFrameT(AppStrings[MSG_PROG_ITXT].as_Str),
                    Child, ColGroup(2),
                        Child, Label1(AppStrings[MSG_BLANKTEST_GAD].as_Str),
                        Child, prog_empty = CheckMark(Config.ProgEmptyTest),
                        Child, Label1(AppStrings[MSG_VERIFY_GAD].as_Str),
                        Child, prog_verify = CheckMark(Config.ProgVerify),
                        End,
                    End,

                Child, HGroup, GroupFrameT(AppStrings[MSG_COPY_ITXT].as_Str),
                    Child, ColGroup(2),
                        Child, Label1(AppStrings[MSG_BLANKTEST_GAD].as_Str),
                        Child, copy_empty = CheckMark(Config.CopyEmptyTest),
                        Child, Label1(AppStrings[MSG_VERIFY_GAD].as_Str),
                        Child, copy_verify = CheckMark(Config.CopyVerify),
                        End,
                    End,

                Child, HGroup, GroupFrameT(AppStrings[MSG_ERASE_ITXT].as_Str),
                    Child, ColGroup(2),
                        Child, Label1(AppStrings[MSG_BLANKTEST_GAD].as_Str),
                        Child, erase_empty = CheckMark(Config.EraseEmptyTest),
                        End,
                    End,

                Child, HSpace(2),

                Child, HGroup,
                    Child, ok = SimpleButton(AppStrings[MSG_OK_GAD].as_Str),
                    End,
                End,
            End;


                                        /* set gadget IDs */

    DoMethod(prog_empty, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, PROG_EMPTY_ID);

    DoMethod(prog_verify, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, PROG_VERIFY_ID);

    DoMethod(copy_empty, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, COPY_EMPTY_ID);

    DoMethod(copy_verify, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, COPY_VERIFY_ID);

    DoMethod(erase_empty, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, ERASE_EMPTY_ID);

    DoMethod(ok, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, OK_GADID);
 
 

                                        /* init cycle chain */

    DoMethod(win, MUIM_Window_SetCycleChain, prog_empty, prog_verify,
             copy_empty, copy_verify, erase_empty, ok, NULL);
 
 
 

    if (win)                    /* window object created? */
    {
        DoMethod(app, OM_ADDMEMBER, win);       /* add win to application */

        set(win, MUIA_Window_Open, TRUE);       /* open window */
        get(win, MUIA_Window_Open, &open);

        if (open)                               /* is window opened? */
        {

            done = FALSE;

            while (!done)
            {
                id = DoMethod(app, MUIM_Application_Input, &signals);

                switch (id)
                {
                    case PROG_EMPTY_ID:
                        Config.ProgEmptyTest = !Config.ProgEmptyTest;
                        break;

                    case PROG_VERIFY_ID:
                        Config.ProgVerify = !Config.ProgVerify;
                        break;

                    case COPY_EMPTY_ID:
                        Config.CopyEmptyTest = !Config.CopyEmptyTest;
                        break;

                    case COPY_VERIFY_ID:
                        Config.CopyVerify = !Config.CopyVerify;
                        break;

                    case ERASE_EMPTY_ID:
                        Config.EraseEmptyTest = !Config.EraseEmptyTest;
                        break;

                    case OK_GADID:
                    case MUIV_Application_ReturnID_Quit:
                        done = TRUE;
                        break;
                }

                if (!done && signals)
                    Wait(signals);              /* wait for the next event */
            }
 

           set(win, MUIA_Window_Open, FALSE);   /* close window */
  
        }

        DoMethod(app, OM_REMMEMBER, win);       /* remove win from app. */

        MUI_DisposeObject(win);                 /* delete window object */
    }



    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */

}





/******************************************************************************
** CompareRequester()
*******************************************************************************
** input:   none
** output:  0: cancel selected or failed to open the window
**          1: compare a GAL with one or several GALs
**          2: compare a GAL with one or several JEDEC files
**          3: compare a JEDEC file with one or several GALs
**
** remarks: opens a window in which can be selected what kind of comparison
**          should be executed
**
******************************************************************************/

int CompareRequester(void)
{
    int   open, done, result;

    ULONG id, signals;

    APTR  win;
    APTR  radio_buttons, cont, cancel;



    set(app, MUIA_Application_Sleep, TRUE);     /* deactivate application */


                                                /* make window object */
    win = WindowObject,
        MUIA_Window_Title, AppStrings[MSG_COMPARISON].as_Str,
        MUIA_Window_CloseGadget, FALSE,
        MUIA_Window_NoMenus, TRUE,
        MUIA_HelpNode, "MenCmp",

            WindowContents, VGroup,
                Child, HCenter(radio_buttons = Radio(AppStrings[MSG_CMPTYPE].as_Str, cmps)),

                Child, HSpace(2),

                Child, HGroup,
                    Child, cont   = SimpleButton(AppStrings[MSG_CONT_GAD].as_Str),
                    Child, cancel = SimpleButton(AppStrings[MSG_CANCEL_GAD].as_Str),
                    End,
                End,
            End;


                                        /* set gadget IDs */

    DoMethod(cont, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, CONT_GADID);


    DoMethod(cancel, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, CANCEL_GADID);



                                        /* init cycle chain */

    DoMethod(win, MUIM_Window_SetCycleChain, radio_buttons, cont, cancel, NULL);




    if (win)                    /* window object created? */
    {
        DoMethod(app, OM_ADDMEMBER, win);       /* add win to application */

        set(win, MUIA_Window_Open, TRUE);       /* open window */
        get(win, MUIA_Window_Open, &open);

        if (open)                               /* is window opened? */
        {

            done = FALSE;

            while (!done)
            {
                id = DoMethod(app, MUIM_Application_Input, &signals);

                switch (id)
                {
                    case CANCEL_GADID:                      /* cancel */
                    case MUIV_Application_ReturnID_Quit:
                        done   = TRUE;
                        result = 0;
                        break;

                    case CONT_GADID:                        /* cont.  */
                        get(radio_buttons, MUIA_Radio_Active, &result);
                        result++;               /* get state of radio */
                        done = TRUE;            /* buttons and return */
                        break;                  /* the result         */
                }

                if (!done && signals)
                    Wait(signals);              /* wait for the next event */
            }


           set(win, MUIA_Window_Open, FALSE);   /* close window */

        }

        DoMethod(app, OM_REMMEMBER, win);       /* remove win from app. */

        MUI_DisposeObject(win);                 /* delete window object */
    }



    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */


    return result;                              /* return result ;-) */
}





/******************************************************************************
** JedecRequester()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: opens the JEDEC preferences window
**
******************************************************************************/

void JedecRequester(void)
{

    int   open, done;

    ULONG id, signals;

    APTR  win;
    APTR  sec, fuse, file, ok;




    set(app, MUIA_Application_Sleep, TRUE);     /* deactivate application */


                                                /* make window object */
    win = WindowObject,
        MUIA_Window_Title, AppStrings[MSG_JEDPARA_WIN].as_Str,
        MUIA_Window_CloseGadget, FALSE,
        MUIA_Window_NoMenus, TRUE,
        MUIA_HelpNode, "MenJEDECPar",

            WindowContents, VGroup,
                Child, HGroup, GroupFrameT(AppStrings[MSG_WRITEJED_ITXT].as_Str),
                    Child, ColGroup(2),
                        Child, Label1(AppStrings[MSG_JEDSEC_GAD].as_Str),
                        Child, sec = CheckMark(Config.JedecSecBit),
                        Child, Label1(AppStrings[MSG_JEDFUSE_GAD].as_Str),
                        Child, fuse = CheckMark(Config.JedecFuseChk),
                        Child, Label1(AppStrings[MSG_JEDFILE_GAD].as_Str),
                        Child, file = CheckMark(Config.JedecFileChk),
                        End,
                    End,

                Child, HSpace(2),

                Child, HGroup,
                    Child, ok = SimpleButton(AppStrings[MSG_OK_GAD].as_Str),
                    End,
                End,
            End;


                                        /* set gadget IDs */

    DoMethod(sec, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, JEDSEC_ID);

    DoMethod(fuse, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, JEDFUSE_ID);

    DoMethod(file, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, JEDFILE_ID);

    DoMethod(ok, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, OK_GADID);
 
 

                                        /* init cycle chain */

    DoMethod(win, MUIM_Window_SetCycleChain, sec, fuse, file, ok, NULL);
 
 

    if (win)                    /* window object created? */
    {
        DoMethod(app, OM_ADDMEMBER, win);       /* add win to application */

        set(win, MUIA_Window_Open, TRUE);       /* open window */
        get(win, MUIA_Window_Open, &open);

        if (open)                               /* is window opened? */
        {

            done = FALSE;

            while (!done)
            {
                id = DoMethod(app, MUIM_Application_Input, &signals);

                switch (id)
                {
                    case JEDSEC_ID:
                        Config.JedecSecBit = !Config.JedecSecBit;
                        break;

                    case JEDFUSE_ID:
                        Config.JedecFuseChk = !Config.JedecFuseChk;
                        break;

                    case JEDFILE_ID:
                        Config.JedecFileChk = !Config.JedecFileChk;
                        break;

                    case OK_GADID:
                        done = TRUE;
                        break;
                }

                if (!done && signals)
                    Wait(signals);              /* wait for the next event */
            }
 

           set(win, MUIA_Window_Open, FALSE);   /* close window */
  
        }

        DoMethod(app, OM_REMMEMBER, win);       /* remove win from app. */

        MUI_DisposeObject(win);                 /* delete window object */
    }



    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */
 
}





/******************************************************************************
** About()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: opens the about window
******************************************************************************/

void About(void)
{
    int   open, done;

    ULONG id, signals;

    APTR  win;
    APTR  ok;



    set(app, MUIA_Application_Sleep, TRUE);     /* deactivate application */

                                                /* make window object */
    win = WindowObject,
        MUIA_Window_Title, AppStrings[MSG_MAIN_MENU1_ITEM1].as_Str,
        MUIA_Window_CloseGadget, FALSE,
        MUIA_Window_NoMenus, TRUE,
        MUIA_HelpNode, "MenAbout",

            WindowContents, VGroup,
                Child, TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, AppStrings[MSG_ABOUT_TXT].as_Str, End,
                Child, ok = SimpleButton(AppStrings[MSG_OK_GAD].as_Str),
                End,
            End;


                                        /* set gadget IDs */

    DoMethod(ok, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, OK_GADID);



                                        /* init cycle chain */

    DoMethod(win, MUIM_Window_SetCycleChain, ok, NULL);




    if (win)                    /* window object created? */
    {
        DoMethod(app, OM_ADDMEMBER, win);       /* add win to application */

        set(win, MUIA_Window_Open, TRUE);       /* open window */
        get(win, MUIA_Window_Open, &open);

        if (open)                               /* is window opened? */
        {

            done = FALSE;

            while (!done)
            {
                id = DoMethod(app, MUIM_Application_Input, &signals);

                switch (id)
                {
                    case OK_GADID:                          /* continue */
                    case MUIV_Application_ReturnID_Quit:
                        done   = TRUE;
                        break;
                }

                if (!done && signals)
                    Wait(signals);              /* wait for the next event */
            }


           set(win, MUIA_Window_Open, FALSE);   /* close window */

        }

        DoMethod(app, OM_REMMEMBER, win);       /* remove win from app. */

        MUI_DisposeObject(win);                 /* delete window object */
    }



    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */

}





/******************************************************************************
** mystrcmp()
*******************************************************************************
** input:   *cptr1      pointer to string 1
**          *cptr2      pointer to string 2
**
** output:  TRUE        strings are not equal
**          FALSE       strings are equal
**
** remarks: This function does compare two strings (deals upper and lower
**          case as the same).
******************************************************************************/
 
int mystrcmp(char *cptr1, char *cptr2)
{

    while (*cptr1 && *cptr2)
    {
        if (tolower(*cptr1) != tolower(*cptr2))
            return TRUE;

        cptr1++;
        cptr2++;
    }


    if (!*cptr1 && !*cptr2)
        return FALSE;
    else
        return TRUE;

}





/******************************************************************************
** MyFileReq()
*******************************************************************************
** input:   *headtxt   requester title
**          *showtxt   suffix
**          showreq    TRUE:  show requester
**                     FALSE: show no requester
**          mode       SAVE/LOAD  save/load-requester
**
** output:  TRUE    o.k. selected
**          FALSE   cancel selected
**
** remarks: opens the reqtools-file-requester
******************************************************************************/

int MyFileReq(char *headtxt, char *showtxt, int showreq, int mode)
{
    int     freq = YES, result;
    char    *pos1, *pos2, *str_buf;
    char    showpattern[10] = "#?";
    char    short_path[35];

    struct  FileLock *lock;



    strcat(showpattern, showtxt);         /* make show pattern */

    rtChangeReqAttr(filereq, RTFI_MatchPat, showpattern, TAG_END);

                                         /* remove suffix and add "showtxt" */
    if (strlen((char *)filename) >= 4)
    {
        pos1 = (char *)(filename + (long)strlen(filename) -
                        (long)strlen(showtxt));

        if ((!mystrcmp(pos1, ".pld")) || (!mystrcmp(pos1, ".jed")) ||
            (!mystrcmp(pos1, ".pin")) || (!mystrcmp(pos1, ".chp")) ||
            (!mystrcmp(pos1, ".fus")))
        {
            *pos1 = 0;
            strcat((char *)&filename[0], showtxt);
        }
    }



    if (showreq)                           /* show requester? */
    {
        set(app, MUIA_Application_Sleep, TRUE);    /* deactivate application */

        freq = (int)rtFileRequest(filereq, filename, headtxt,
                                  RT_ReqPos,  REQPOS_CENTERSCR,
                                  RTFI_Flags, FREQF_PATGAD, TAG_END);

        set(app, MUIA_Application_Sleep, FALSE);   /* reactivate application */
    }


    if ((showreq && freq) || !showreq)
    {

        if (strlen((char *)filename) >= 4)
        {                                       /* add suffix */

            pos1 = (char *)(filename + (long)strlen(filename) -
                           (long)strlen(showtxt));

            if (mystrcmp(pos1, showtxt))   /* add suffix if there is none */
            {
                strcat(filename, showtxt);
                strcat(path, showtxt);
            }

        }
        else
        {

            if (!strlen(filename))           /* no file entered? */
                return FALSE;                /* then cancel      */

            strcat(filename, showtxt);
            strcat(path, showtxt);
        }


                                            /* compose path */
        strcpy(path, filereq->Dir);

        pos1 = (char *)(filereq->Dir + ((long)strlen(filereq->Dir) - 1L));
        pos2 = (char *)(path + ((long)strlen(path)));

        if (!((*pos1 == ':') || (*pos1 == '/') || !*pos1))
        {
            *pos2++ = '/';
            *pos2   = 0x00;                 /* end of string */
        }

        strcat(path, filename);



        if (!strcmp(showtxt, ".pld"))       /* copy dir+filename of the */
            strcpy(prevSourceFile, path);   /* source file to buffer */



        if (showreq && (mode == SAVE))      /* if this is a SAVE-requester   */
        {                                   /* test whether or not this file */
                                            /* does already exist            */

            if ((lock = (struct FileLock *)Lock((BYTE *)path,
                                                (long)ACCESS_READ)))
            {
                UnLock((BPTR)lock);

                set(app, MUIA_Application_Sleep, TRUE);   /* let appl. sleep */

                                                /* show text: "file 'xyz' */
                                                /* already exists" */
                if ((str_buf = (char *)AllocMem(
                                    strlen(AppStrings[MSG_SAVEOVER].as_Str) +
                                    sizeof(short_path), MEMF_PUBLIC)))
                {
                                                /* limit length of path name */

                    if (strlen(path) > sizeof(short_path) - 1)
                    {
                        short_path[0] = '.';    /* make path shorter */
                        short_path[1] = '.';
                        short_path[2] = '.';
                        short_path[3] = 0;

                        strcat(short_path,
                               &path[strlen(path) - sizeof(short_path) + 5]);
                    }
                    else
                    {
                        strcpy(short_path, path);
                    }
                                            /* make text to be displayed */

                    sprintf(str_buf, AppStrings[MSG_SAVEOVER].as_Str,
                                                                short_path);
                    result = TxtRequest(str_buf,
                                        AppStrings[MSG_CONT_GAD].as_Str,
                                        AppStrings[MSG_CANCEL_GAD].as_Str);
                    FreeMem(str_buf, strlen(AppStrings[MSG_SAVEOVER].as_Str) +
                                     sizeof(short_path));
                }


                set(app, MUIA_Application_Sleep, FALSE);   /* wake up appl. */

                if (!result)               /* call again, if canceled */
                    return (MyFileReq(headtxt, showtxt, showreq, mode));
            }
        }

        return TRUE;

    }
    else
    {
        return FALSE;
    }

    return FALSE;           /* just to keep the compiler happy */
}





/******************************************************************************
** TxtRequest()
*******************************************************************************
** input:   *text           text to show
**          *gadget1_txt    text for first gadget
**          *gadget2_txt    text for second gadget
**
** output:  one gadget:   0: error or gadget selected
**          two gadgets:  0: error or second gadget selected
**                        1: first gadget selected
**
** remarks: This function opens a requester with one or two gadgets. If
**          *gadget2_txt is NULL, only one gadget is displayed else two.
**          The parameter *gadget1_txt must always be not equal NULL!
******************************************************************************/

int TxtRequest(UBYTE *text, UBYTE *gadget1_txt, UBYTE *gadget2_txt)
{
    int   result;
    int   open, done;

    ULONG id, signals;

    APTR  win;
    APTR  gad1, gad2;



    set(app, MUIA_Application_Sleep, TRUE);   /* deactivate the application */


                                                /* make window object */
    if (gadget2_txt)
    {
        win = WindowObject,
            MUIA_Window_Title, AppStrings[MSG_REQUEST_WIN].as_Str,
            MUIA_Window_CloseGadget, FALSE,
            MUIA_Window_NoMenus, TRUE,
            MUIA_HelpNode, "Main",

                WindowContents, VGroup,
                    Child, TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, text, End,
                    Child, HGroup,
                        Child, gad1 = SimpleButton(gadget1_txt),
                        Child, gad2 = SimpleButton(gadget2_txt),
                        End,
                    End,
                End;
                                        /* set gadget IDs */

        DoMethod(gad1, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, 2);

        DoMethod(gad2, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, 1);

                                        /* init cycle chain */

        DoMethod(win, MUIM_Window_SetCycleChain, gad1, gad2, NULL);
    }
    else
    {
        win = WindowObject,
            MUIA_Window_Title, AppStrings[MSG_REQUEST_WIN].as_Str,
            MUIA_Window_CloseGadget, FALSE,
            MUIA_Window_NoMenus, TRUE,
            MUIA_HelpNode, "Main",

                WindowContents, VGroup,
                    Child, TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, text, End,
                    Child, gad1 = SimpleButton(gadget1_txt),
                    End,
                End;
                                        /* set gadget IDs */

        DoMethod(gad1, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, 1);

                                        /* init cycle chain */

        DoMethod(win, MUIM_Window_SetCycleChain, gad1, NULL);
    }




    if (win)                    /* window object created? */
    {
        DoMethod(app, OM_ADDMEMBER, win);       /* add win to application */

        set(win, MUIA_Window_Open, TRUE);       /* open window */
        get(win, MUIA_Window_Open, &open);

        if (open)                               /* is window opened? */
        {

            done = FALSE;

            while (!done)
            {
                id = DoMethod(app, MUIM_Application_Input, &signals);

                switch (id)
                {
                    case 1:
                    case MUIV_Application_ReturnID_Quit:
                        done   = TRUE;
                        result = 0;
                        break;

                    case 2:
                        done   = TRUE;
                        result = 1;
                        break;
                }

                if (!done && signals)
                    Wait(signals);              /* wait for the next event */
            }


           set(win, MUIA_Window_Open, FALSE);   /* close window */

        }

        DoMethod(app, OM_REMMEMBER, win);       /* remove win from app. */

        MUI_DisposeObject(win);                 /* delete window object */
    }


    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */


    return result;
}





/******************************************************************************
** GALTypeRequest()
*******************************************************************************
** input:   *text   text to show
**
** output:  0       cancel or error
**          1       GAL16V8 selected
**          2       GAL20V8 selected
**          3       GAL22V10 selected
**          4       GAL20RA10 selected
**
** remarks: This function opens a requester in which a GAL type can be
**          selected, if the GAL type selection option is true.
**          If the GAL type selection option is not active, a continue/cancel
**          requester will be opened.
******************************************************************************/

int GALTypeRequest(UBYTE *text)
{
    int   open, done, result;

    ULONG id, signals;

    APTR  win;
    APTR  radio_buttons, cont, cancel;

    static char *radio_txt[5];



    result = 0;


    if (Config.GALTypeReq)                    /* GAL type selection active? */
    {

        if (hw_version <= HW_GALER_1_2)       /* init text of radio buttons */
        {
            radio_txt[0] = "GAL16V8";
            radio_txt[1] = "GAL20V8";
            radio_txt[2] = NULL;
        }
        else
        {
            radio_txt[0] = "GAL16V8";
            radio_txt[1] = "GAL20V8";
            radio_txt[2] = "GAL22V10";
            radio_txt[3] = "GAL20RA10";
            radio_txt[4] = NULL;
        }



        set(app, MUIA_Application_Sleep, TRUE);   /* deactivate application */


                                            /* make window object */
        win = WindowObject,
            MUIA_Window_Title, NULL,
            MUIA_Window_CloseGadget, FALSE,
            MUIA_Window_NoMenus, TRUE,
            MUIA_HelpNode, "MenTypeReq",

                WindowContents, VGroup,
                    Child, TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, text, End,

                    Child, HCenter(radio_buttons = Radio(AppStrings[MSG_MAIN_MENU2].as_Str, radio_txt)),

                    Child, HSpace(2),

                    Child, HGroup,
                        Child, cont   = SimpleButton(AppStrings[MSG_CONT_GAD].as_Str),
                        Child, cancel = SimpleButton(AppStrings[MSG_CANCEL_GAD].as_Str),
                        End,
                    End,
                End;


                                            /* set gadget IDs */

        DoMethod(cont, MUIM_Notify, MUIA_Pressed, FALSE,
                 app, 2, MUIM_Application_ReturnID, CONT_GADID);


        DoMethod(cancel, MUIM_Notify, MUIA_Pressed, FALSE,
                 app, 2, MUIM_Application_ReturnID, CANCEL_GADID);


                                            /* init cycle chain */

        DoMethod(win, MUIM_Window_SetCycleChain, radio_buttons, cont, cancel, NULL);


                                            /* activate current GAL-type gadget */
        switch (GALType)
        {
            case GAL16V8:
                set(radio_buttons, MUIA_Radio_Active, 0);
                break;

            case GAL20V8:
                set(radio_buttons, MUIA_Radio_Active, 1);
                break;

            case GAL22V10:
                set(radio_buttons, MUIA_Radio_Active, 2);
                break;

            case GAL20RA10:
                set(radio_buttons, MUIA_Radio_Active, 3);
                break;
         }



        if (win)                    /* window object created? */
        {
            DoMethod(app, OM_ADDMEMBER, win);       /* add win to application */

            set(win, MUIA_Window_Open, TRUE);       /* open window */
            get(win, MUIA_Window_Open, &open);

            if (open)                               /* is window opened? */
            {

                done = FALSE;

                while (!done)
                {
                    id = DoMethod(app, MUIM_Application_Input, &signals);

                    switch (id)
                    {
                        case CANCEL_GADID:                      /* cancel */
                        case MUIV_Application_ReturnID_Quit:
                            done   = TRUE;
                            result = 0;
                            break;

                        case CONT_GADID:                        /* cont.  */
                            get(radio_buttons, MUIA_Radio_Active, &result);
                            result++;               /* get state of radio */
                            done = TRUE;            /* buttons and return */
                            break;                  /* the result         */
                    }

                    if (!done && signals)
                        Wait(signals);              /* wait for the next event */
                }


               set(win, MUIA_Window_Open, FALSE);   /* close window */

            }

            DoMethod(app, OM_REMMEMBER, win);       /* remove win from app. */

            MUI_DisposeObject(win);                 /* delete window object */
        }



        set(app, MUIA_Application_Sleep, FALSE);  /* reactivate application */



        switch(result)
        {
            case 1:
                SetGALType(GAL16V8);        /* GAL16V8 selected */
                break;

            case 2:
                SetGALType(GAL20V8);        /* GAL20V8 selected */
                break;

            case 3:
                SetGALType(GAL22V10);       /* GAL22V10 selected */
                break;

            case 4:
                SetGALType(GAL20RA10);      /* GAL20RA10 selected */
                break;
        }

    }
    else
    {
        result = TxtRequest(text, AppStrings[MSG_CONT_GAD].as_Str,
                                  AppStrings[MSG_CANCEL_GAD].as_Str);
    }


    return result;
}





/******************************************************************************
** AsmRequest()
*******************************************************************************
** input:   none
**
** output:  TRUE   continue selected
**          FALSE  cancel selected
**
** remarks: opens the assembler options window
**
******************************************************************************/

int AsmRequester(void)
{
    int   open, done, result;

    ULONG id, signals;

    APTR  win;
    APTR  cont, cancel;
    APTR  jedec, fuse, chip, pin, autosave, type;




    set(app, MUIA_Application_Sleep, TRUE);     /* deactivate application */


                                                /* make window object */
    win = WindowObject,
        MUIA_Window_Title, "Assembler",
        MUIA_Window_CloseGadget, FALSE,
        MUIA_Window_NoMenus, TRUE,
        MUIA_HelpNode, "Assembler",

            WindowContents, VGroup,
                Child, HGroup, GroupFrameT(AppStrings[MSG_WRITEFILES_ITXT].as_Str),
                    Child, ColGroup(2),
                        Child, Label1(AppStrings[MSG_MAKEJED_GAD].as_Str),
                        Child, jedec = CheckMark(Config.GenJedec),
                        Child, Label1(AppStrings[MSG_MAKEFUSE_GAD].as_Str),
                        Child, fuse = CheckMark(Config.GenFuse),
                        Child, Label1(AppStrings[MSG_MAKECHIP_GAD].as_Str),
                        Child, chip = CheckMark(Config.GenChip),
                        Child, Label1(AppStrings[MSG_MAKEPIN_GAD].as_Str),
                        Child, pin = CheckMark(Config.GenPin),
                       End,
                    End,

                Child, HGroup,
                    Child, ColGroup(2),
                        Child, Label1(AppStrings[MSG_AUTOSAVE_GAD].as_Str),
                        Child, autosave = CheckMark(Config.AutoSave),
                        Child, Label1(AppStrings[MSG_ADJUSTGAL_GAD].as_Str),
                        Child, type = CheckMark(Config.AutoGAL),
                        End,
                    End,

                Child, HSpace(2),

                Child, HGroup,
                    Child, cont   = SimpleButton(AppStrings[MSG_CONT_GAD].as_Str),

                    Child, VSpace(4),

                    Child, cancel = SimpleButton(AppStrings[MSG_CANCEL_GAD].as_Str),
                    End,
                End,
            End;


                                        /* set gadget IDs */

    DoMethod(jedec, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, MAKEJED_ID);

    DoMethod(fuse, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, MAKEFUSE_ID);

    DoMethod(chip, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, MAKECHIP_ID);

    DoMethod(pin, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, MAKEPIN_ID);

    DoMethod(autosave, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, AUTOSAVE_ID);

    DoMethod(type, MUIM_Notify, MUIA_Selected, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, ADJUSTGAL_ID);

    DoMethod(cont, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, CONT_GADID);
 
    DoMethod(cancel, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, CANCEL_GADID);
 
 
 
                                        /* init cycle chain */

    DoMethod(win, MUIM_Window_SetCycleChain, jedec, fuse, chip, pin,
             autosave, type, cont, cancel, NULL);
 


    if (win)                    /* window object created? */
    {
        DoMethod(app, OM_ADDMEMBER, win);       /* add win to application */

        set(win, MUIA_Window_Open, TRUE);       /* open window */
        get(win, MUIA_Window_Open, &open);

        if (open)                               /* is window opened? */
        {

            done = FALSE;

            while (!done)
            {
                id = DoMethod(app, MUIM_Application_Input, &signals);

                switch (id)
                {
                    case CONT_GADID:         /* continue */
                        done = TRUE;
                        result = TRUE;
                        break;

                    case CANCEL_GADID:       /* cancel */
                        done = TRUE;
                        result = FALSE;
                        break;

                    case MAKEJED_ID:
                        Config.GenJedec = !Config.GenJedec;
                        break;

                    case MAKEFUSE_ID:
                        Config.GenFuse = !Config.GenFuse;
                        break;

                    case MAKECHIP_ID:
                        Config.GenChip = !Config.GenChip;
                        break;

                    case MAKEPIN_ID:
                        Config.GenPin = !Config.GenPin;
                        break;

                    case AUTOSAVE_ID:
                        Config.AutoSave = !Config.AutoSave;
                        break;

                    case ADJUSTGAL_ID:
                        Config.AutoGAL = !Config.AutoGAL;
                        break;
                }

                if (signals && !done)
                    Wait(signals);              /* wait for the next event */
            }
 

           set(win, MUIA_Window_Open, FALSE);   /* close window */
  
        }

        DoMethod(app, OM_REMMEMBER, win);       /* remove win from app. */

        MUI_DisposeObject(win);                 /* delete window object */
    }


    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */
 
    return result;
}





/******************************************************************************
** FileSize()
*******************************************************************************
** input:   *filename   filename
**
** output:  -1   file does not exist
**          -2   not enough memory for FileInfoBlock
**          >0   length of the specified file
**
** remarks: returns length of a file
**
******************************************************************************/
 
long FileSize(UBYTE *filename)
{
    struct  FileInfoBlock  *fib;
    struct  FileLock       *lock;
    LONG    filesize;


    if ((lock = (struct FileLock *)Lock((BYTE *)filename, (long)ACCESS_READ)))
    {

        fib = (struct FileInfoBlock *)
              AllocMem((long)sizeof(struct FileInfoBlock), MEMF_CHIP);

        if (fib != NULL)
        {
            if (Examine((BPTR)lock, fib))
                filesize = fib->fib_Size;
            else
                filesize = -1L;

            UnLock((BPTR)lock);

            FreeMem(fib,(long)sizeof(struct FileInfoBlock));

            return (filesize);
        }
        else
        {
            return -2L;                         /* not enough free memory */
        }
    }
    else
    {
        return -1L;                             /* file does not exist */
    }
}





/******************************************************************************
** ReadFile()
*******************************************************************************
** input:   *filename       name of file
**          filesize        length of file [bytes]
**          *filebuff       where to store the specified file
**
** output:  TRUE:  file loaded
**          FALSE: failed to load
**
** remarks: loads the specified file into memory
**
******************************************************************************/

int ReadFile(UBYTE *filename, LONG filesize, UBYTE *filebuff)
{
    long  actlength;
    BPTR  fh;


    if ((fh = Open((char *)filename, (long)MODE_OLDFILE)))
    {
        actlength = Read(fh, (char *)filebuff, filesize);
        Close(fh);

        if (actlength == -1L)
            return FALSE;
        else
            return TRUE;
    }

    return FALSE;
}





/******************************************************************************
** ErrorReq()
*******************************************************************************
** input:   errornum    error number
** output:  none
**
** remarks: opens a requester and shows the error messages specified by
**          errornum
******************************************************************************/
 
void ErrorReq(int errornum)
{


    set(app, MUIA_Application_Sleep, TRUE); /* deactivate the application */
 

    switch (errornum)
    {
        case  1:
            TxtRequest(AppStrings[MSG_ERR1].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case  2:
            TxtRequest(AppStrings[MSG_ERR2].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case  3:
            TxtRequest(AppStrings[MSG_ERR3].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case  4:
            TxtRequest(AppStrings[MSG_ERR4].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case  5:
            TxtRequest(AppStrings[MSG_ERR5].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case  6:
            TxtRequest(AppStrings[MSG_ERR6].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case  7:
            TxtRequest(AppStrings[MSG_ERR7].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case  8:
            TxtRequest(AppStrings[MSG_ERR8].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case  9:
            TxtRequest(AppStrings[MSG_ERR9].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case 10:
            TxtRequest(AppStrings[MSG_ERR10].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case 11:
            TxtRequest(AppStrings[MSG_ERR11].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case 12:
            TxtRequest(AppStrings[MSG_ERR12].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;

        case 13:
            TxtRequest(AppStrings[MSG_ERR13].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);
            break;
    }


    set(app, MUIA_Application_Sleep, FALSE); /* reactivate the application */

}





/******************************************************************************
** PrintText()
*******************************************************************************
** input:   *text    pointer to text
**          newline  TRUE:  begin text in a new line
**                   FALSE: add this text to the last list entry
**
** output:  none
**
** remarks: prints text into text field
******************************************************************************/

void PrintText(UBYTE *txt, int newline)
{
    #define LINE_LENGTH  100                 /* max. length of string */


    int     cntr, start_pos;
    char    line[LINE_LENGTH], *string;

    LONG    entries;




    get(LV_text, MUIA_List_Entries, &entries);   /* get number of entries */

    while (entries > MAX_NUM_OF_LINES)  /* if there are too many entries, */
    {                                   /* remove some                    */

        DoMethod(LV_text, MUIM_List_Remove, MUIV_List_Remove_First);
        entries--;

    }


    start_pos = 0;

    if (!newline && entries)
    {

                                                            /* get last entry */
        DoMethod(LV_text, MUIM_List_GetEntry, entries-1, &string);
 
                                                  /* does entry really exist? */

        if (string && (start_pos = strlen(string)))
        {
            strcpy(line, string);           /* copy list view entry into a  */
                                            /* buffer and remove this entry */

            DoMethod(LV_text, MUIM_List_Remove, entries-1);
        }
    }



    while (TRUE)
    {
        cntr = start_pos;                   /* search CR or end of */
        line[start_pos] = 0;                /* string              */

        while (*txt != 0x00 && *txt != 0x0A && cntr < LINE_LENGTH)
        {
            line[cntr++] = *txt++;             /* copy line into line-array */
        }


        line[cntr] = 0;                        /* set end of line */


        DoMethod(LV_text, MUIM_List_InsertSingle,  /* add line to  */
                 line, MUIV_List_Insert_Bottom);   /* the listview */

        if (!*txt)                             /* end of string reached? */
            break;

        txt++;
        start_pos = 0;                       /* begin new line at column 0 */
    }

                                             /* make last entry visible */

    DoMethod(LV_text, MUIM_List_Jump, MUIV_List_Jump_Bottom);

}





/******************************************************************************
** PrintErrorLine()
*******************************************************************************
** input:   line    line number to be printed
**
** output:  none
**
** remarks: prints error text with a line number
******************************************************************************/
 
void PrintErrorLine(int line)
{

  sprintf((char *)&ErrorLineStr[16], "%4d:", line);

  PrintText(&ErrorLineStr[0],1);

}





/******************************************************************************
** LoadConfig()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: does load the configuration file "s:GALer.config"
******************************************************************************/

void LoadConfig(void)
{

    LONG  filelength;
    BPTR  fh;
                                        /* get configuration file */

    if ((fh = Open((char *)"s:GALer.config", (long)MODE_OLDFILE)))
    {
        filelength = Read(fh, (char *)&DummyConfig,
                          (long)sizeof(struct Configuration));
        Close(fh);

        if (filelength == -1L)
            ErrorReq(10);
        else                            /* read error? */
            Config = DummyConfig;       /* then take the defaults */
    }


    GALType = UNKNOWN;

    SetGALType(Config.GALType);         /* set type of GAL */

    GALType = Config.GALType;


                                        /* GAL type requester */
    if (Config.GALTypeReq)
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_TYPEREQ, TRUE);
 

    hw_version = Config.HardwareVersion;        /* hardware version */

    switch (Config.HardwareVersion)
    {
        case HW_GALER_1_0:
            DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_VER11, TRUE);
            break;

        case HW_GALER_1_2:
            DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_VER12, TRUE);
            break;

        case HW_GALER_1_3:
            DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_VER13, TRUE);
            break;

        case HW_ELEKTOR_II:
            DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_VERELEKTOR, TRUE);
            DoMethod(main_win, MUIM_Window_SetMenuState, MEN_CALLCHECKER, FALSE);
            break;
    }



    if (hw_version <= HW_GALER_1_2)             /* enable/disable the 22V10 */
    {                                           /* and the 20RA10 menu      */
        DoMethod(main_win, MUIM_Window_SetMenuState, MEN_22V10,  FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuState, MEN_20RA10, FALSE);
 
                                        /* hardware versions less or   */
                                        /* equal 1.2 do not support    */
                                        /* GAL22V10 and GAL20RA10 GALs */
        if (GALType == GAL22V10 || GALType == GAL20RA10)
            SetGALType(GAL16V8);
    }
    else
    {
        DoMethod(main_win, MUIM_Window_SetMenuState, MEN_22V10,  TRUE);
        DoMethod(main_win, MUIM_Window_SetMenuState, MEN_20RA10, TRUE);
    }

}





/******************************************************************************
** SaveConfig()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: saves configuration to the file s:GALer.config
**
******************************************************************************/
 
void SaveConfig(void)
{
    long  filelength;
    BPTR  fh;



    Config.GALType = GALType;

                                    /* save configuration file */

    if ((fh = Open((char *)"s:GALer.config", (long)MODE_NEWFILE)))
    {
        filelength = Write(fh, (char *)&Config,
                           (long)sizeof(struct Configuration));

        Close(fh);

        if (filelength == -1L)
            ErrorReq(11);           /* file does not exist */
    }
    else
    {
        ErrorReq(11);               /* file does not exist */
    }

}





/******************************************************************************
** SetGALType()
*******************************************************************************
** input:   galtype   type of GAL
** output:  none
**
** remarks: This function does set all variables according to the new
**          type of GAL.
******************************************************************************/
 
void SetGALType(int galtype)
{

    if (galtype == GAL16V8 && GALType != GAL16V8)
    {
        GALType    = GAL16V8;
        MaxFuseAdr = MAX_FUSE_ADR16;
        RowSize    = ROW_SIZE_16V8;
        XORSize    = 8;
        SigAdr     = SIG_ADR16;

        SetGAL(GAL16V8);

        SetSymbolGAL(GAL16V8);

        strncpy ((char *)&main_win_title[56], (char *)"GAL16V8  ", (size_t)9);

                                        /* set type menu to GAL16V8 */
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_16V8,   TRUE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_20V8,   FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_22V10,  FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_20RA10, FALSE);
    }


    if (galtype == GAL20V8 && GALType != GAL20V8)
    {
        GALType    = GAL20V8;
        MaxFuseAdr = MAX_FUSE_ADR20;
        RowSize    = ROW_SIZE_20V8;
        XORSize    = 8;
        SigAdr     = SIG_ADR20;

        SetGAL(GAL20V8);

        SetSymbolGAL(GAL20V8);

        strncpy ((char *)&main_win_title[56], (char *)"GAL20V8  ", (size_t)9);

                                        /* set type menu to GAL20V8 */
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_16V8,   FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_20V8,   TRUE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_22V10,  FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_20RA10, FALSE);
    }


    if (galtype == GAL22V10 && GALType != GAL22V10)
    {
        GALType    = GAL22V10;
        MaxFuseAdr = MAX_FUSE_ADR22V10;
        RowSize    = ROW_SIZE_22V10;
        XORSize    = 10;
        SigAdr     = SIG_ADR22V10;

        SetGAL(GAL22V10);

        SetSymbolGAL(GAL22V10);

        strncpy ((char *)&main_win_title[56], (char *)"GAL22V10 ", (size_t)9);

                                        /* set type menu to GAL22V10 */
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_16V8,   FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_20V8,   FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_22V10,  TRUE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_20RA10, FALSE);
    }


    if (galtype == GAL20RA10 && GALType != GAL20RA10)
    {
        GALType    = GAL20RA10;
        MaxFuseAdr = MAX_FUSE_ADR20RA10;
        RowSize    = ROW_SIZE_20RA10;
        XORSize    = 10;
        SigAdr     = SIG_ADR20RA10;

        SetGAL(GAL20RA10);

        SetSymbolGAL(GAL20RA10);

        strncpy ((char *)&main_win_title[56], (char *)"GAL20RA10", (size_t)9);

                                        /* set type menu to GAL20RA10 */
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_16V8,   FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_20V8,   FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_22V10,  FALSE);
        DoMethod(main_win, MUIM_Window_SetMenuCheck, MEN_20RA10, TRUE);
    }


    set(main_win, MUIA_Window_Title, main_win_title);
}





/* The functions AddByte(), AddString(), IncPointer(), DecPointer() */
/* and FreeBuffer() are useful for handling chained lists           */

/******************************************************************************
** AddByte()
*******************************************************************************
** input:   *buff   pointer to buffer structure
**          code    byte to add to the list
**
** output:  0:   o.k.
*           !=0: error occured (e.g. not enough free memory)
**
** remarks: This function does set a byte in a buffer. If the end of the buffer
**          is reached, a new buffer is added to the chained list of buffers.
**
******************************************************************************/

int AddByte(struct ActBuffer *buff, UBYTE code)
{
    struct  Buffer  *mybuff;


    if ((buff->Entry) < (buff->BuffEnd))    /* is the current address within */
    {                                       /* the buffer ?                  */
        *buff->Entry++ = code;              /* the fill in the byte */
    }
    else
    {                                       /* if not, then add a new buffer */
        if (!(mybuff = (struct Buffer *)AllocMem((long)sizeof(struct Buffer),
                                                 MEMF_PUBLIC|MEMF_CLEAR)))
        {
            ErrorReq(2);
            return(-1);
        }


        buff->ThisBuff->Next = mybuff;      /* new buffer is current buffer */
        mybuff->Prev   = buff->ThisBuff;    /* previous is old buffer       */
        buff->ThisBuff = mybuff;            /* current buffer is new buffer */
        buff->Entry    = (UBYTE *)(&mybuff->Entries[0]);
        buff->BuffEnd  = (UBYTE *)mybuff + (long)sizeof(struct Buffer);
        *buff->Entry++ = code;
    }


    return(0);
}





/******************************************************************************
** AddString()
*******************************************************************************
** input:   *buff    pointer to buffer structure
**          strnptr  pointer to string to be added to the buffer
**
** output:  0:   o.k.
*           !=0: error occured (e.g. not enough free memory)
**
** remarks: This function does add a string to a buffer. If the end of the
**          buffer is reached, a new buffer is added to the chained list of
**          buffers.
**
******************************************************************************/
 
int AddString(struct ActBuffer *buff, UBYTE *strnptr)
{

    while (*strnptr)
    {
        if (AddByte(buff, *strnptr++))
            return(-1);
    }

    return(0);
}





/******************************************************************************
** IncPointer()
*******************************************************************************
** input:   *buff   pointer to buffer structure
**
** output:  none
**
** remarks: This function does increment the pointer of the current buffer
**          structure. If the pointer points to the end of the buffer, the
**          pointer will be set to the beginning of the next entry of the
**          chained list.
**          ATTENTION: there is no test whether the absolut end of the chained
**                     list is reached or not!
**
******************************************************************************/
 
void IncPointer(struct ActBuffer *buff)
{

    buff->Entry++;

    if (buff->Entry == buff->BuffEnd)       /* end of buffer reached? */
    {
        buff->ThisBuff = buff->ThisBuff->Next;  /* yes, then set the pointer */
                                                /* to the next buffer        */

        buff->Entry    = (UBYTE *)(&buff->ThisBuff->Entries[0]);

        buff->BuffEnd  = (UBYTE *)buff->ThisBuff + (long)sizeof(struct Buffer);
    }

}





/******************************************************************************
** DecPointer()
*******************************************************************************
** input:   *buff   pointer to buffer structure
**
** output:  none
**
** remarks: This function does decrement the pointer of the current buffer
**          structure. If the pointer points to the start of the buffer, the
**          pointer will be set to the beginning of the previous entry of the
**          chained list.
**          ATTENTION: there is no test whether the absolut start of the chained
**                     list is reached or not!
**
******************************************************************************/

void DecPointer(struct ActBuffer *buff)
{

    buff->Entry--;

    if (buff->Entry < &buff->ThisBuff->Entries[0])  /* start of buffer reached? */
    {
        buff->ThisBuff = buff->ThisBuff->Prev;    /* pointer to previous buffer */

        buff->BuffEnd  = (UBYTE *)buff->ThisBuff + (long)sizeof(struct Buffer);

        buff->Entry    = (UBYTE *)((buff->BuffEnd)-1L);
    }

}





/******************************************************************************
** FreeBuffer()
*******************************************************************************
** input:   *buff   pointer to buffer structure
**
** output:  none
**
** remarks: This function does free memory which is allocated by the chained
**          list.
**
******************************************************************************/

void FreeBuffer(struct Buffer *buff)
{
    struct  Buffer  *nextbuff;

    do
    {
        nextbuff = buff->Next;

        FreeMem(buff, (long)sizeof(struct Buffer));
    }
    while (buff = nextbuff);

}





/******************************************************************************
** SelectEditor()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: This function does open a window in which the editor
**          can be selected.
**
******************************************************************************/
 
void SelectEditor(void)
{

    int    open, done;

    ULONG  id, signals;

    APTR   win;
    APTR   ok_gad, string_gad;

    STRPTR string;




    set(app, MUIA_Application_Sleep, TRUE);     /* deactivate application */

                                                /* make window object */
    win = WindowObject,
        MUIA_Window_Title, AppStrings[MSG_SELEDITOR_WIN].as_Str,
        MUIA_Window_CloseGadget, FALSE,
        MUIA_Window_NoMenus, TRUE,
        MUIA_HelpNode, "MenEditor",

            WindowContents, VGroup,
                Child, HGroup,
                    Child, Label2(AppStrings[MSG_EDITOR].as_Str),
                    Child, string_gad = String(Config.EditorStr, EDITOR_STR_SIZE),
                    End,
 
                Child, HGroup,
                    Child, ok_gad = SimpleButton(AppStrings[MSG_OK_GAD].as_Str),
                    End,
                End,
            End;

                                        /* set gadget IDs */

    DoMethod(string_gad, MUIM_Notify, MUIA_String_Acknowledge, MUIV_EveryTime,
             app, 2, MUIM_Application_ReturnID, EDITORSTRING_ID);
 
    DoMethod(ok_gad, MUIM_Notify, MUIA_Pressed, FALSE,
             app, 2, MUIM_Application_ReturnID, OK_GADID);


                                        /* init cycle chain */

    DoMethod(win, MUIM_Window_SetCycleChain, string_gad, ok_gad, NULL);
 
 
 

    if (win)                    /* window object created? */
    {
        DoMethod(app, OM_ADDMEMBER, win);       /* add win to application */

        set(win, MUIA_Window_Open, TRUE);       /* open window */
        get(win, MUIA_Window_Open, &open);

        if (open)                               /* is window opened? */
        {

            done = FALSE;

            while (!done)
            {
                id = DoMethod(app, MUIM_Application_Input, &signals);

                switch (id)
                {
                    case OK_GADID:              /* copy string into buffer */
                    case EDITORSTRING_ID:
                        get(string_gad, MUIA_String_Contents, &string);
                        strcpy(Config.EditorStr, string);
                        done = TRUE;                        /* that's it */
                        break;
                }

                if (!done && signals)
                    Wait(signals);              /* wait for the next event */
            }
 

           set(win, MUIA_Window_Open, FALSE);   /* close window */
  
        }

        DoMethod(app, OM_REMMEMBER, win);       /* remove win from app. */

        MUI_DisposeObject(win);                 /* delete window object */
    }



    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */
 
}





/******************************************************************************
** CallEditor()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: Call editor and replace %s with the current *.pld-file.
**
******************************************************************************/

void CallEditor(void)
{
    char  callstrn[100 + EDITOR_STR_SIZE];
    BPTR  ofh;



    set(app, MUIA_Application_Sleep, TRUE);     /* deactivate application */
 

    if (ofh = Open("NIL:", (long)MODE_NEWFILE))
    {                                           /* open file handle */

        if (strlen(prevSourceFile) <= 100)
        {                                       /* is string too long? */

            sprintf(&callstrn[0], Config.EditorStr, prevSourceFile);

            if (Execute(&callstrn[0], NULL, ofh) == FALSE)
                TxtRequest(AppStrings[MSG_CALLED_ERR].as_Str,
                       AppStrings[MSG_CANCEL_GAD].as_Str, NULL);

        }

        Close(ofh);                             /* close output file handle */

    }


    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */

}





/******************************************************************************
** WaitForTimer()
*******************************************************************************
** input:   micro:  time to wait in micro seconds
**
** output:  none
**
** remarks: does wait a time
******************************************************************************/
 
void WaitForTimer(ULONG micro)
{

    timereq->tr_node.io_Command = TR_ADDREQUEST;
    timereq->tr_time.tv_secs    = 0;
    timereq->tr_time.tv_micro   = micro;

    DoIO((struct IORequest *)timereq);
}



 

/******************************************************************************
** HelpOnHelp()
*******************************************************************************
** input:   none
** output:  none
**
** remarks: does show how to get help on something
******************************************************************************/

void HelpOnHelp(void)
{

    set(app, MUIA_Application_Sleep, TRUE);     /* deactivate application */


    TxtRequest(AppStrings[MSG_HELP_TXT].as_Str, AppStrings[MSG_OK_GAD].as_Str,
                                                                        NULL);

    set(app, MUIA_Application_Sleep, FALSE);    /* reactivate application */

}





/* EOF */
