/********************************************************************/
/* Modulname      : GAMEFIX.C                                       */
/* Autor          : Thomas Binder                                   */
/* Zweck          : Verbesserung der Abw„rtskompatibilit„t des      */
/*                  Falcon030. Einstellprogramm mit GEM-Bedienung,  */
/*                  das auch das Abspeichern kleiner Startpro-      */
/*                  gramme erm”glicht.                              */
/* Compiler       : Pure C 1.0                                      */
/* Erstellt am    : 10.08.1993                                      */
/* Letzte Žnderung: 03.09.1993                                      */
/********************************************************************/

#include <aes.h>
#include <tos.h>
#include <falcon.h>
#include <portab.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include "gamefix.rsh"
#include "gamefix.h"
#include "mini1.hex"
#include "mini2.hex"

/* Prototypen */
LONG reset(void);
LONG get_settings(void);
LONG set(void);
WORD do_dialog(OBJECT *tree, WORD sobj,
    WORD (*action)(OBJECT *tree, WORD obj));
WORD handle_savedial(OBJECT *tree, WORD obj);
WORD handle_maindial(OBJECT *tree, WORD obj);
void cross(OBJECT *tree, WORD obj);
void set_atten(WORD redraw);
void boot(void);
void save(void);
WORD do_save(char *rout, LONG size);
WORD take_settings(void);
void put_settings(void);
WORD tree_walk(OBJECT *tree, WORD start,
WORD (*action)(OBJECT *tree, WORD obj));
WORD adapt_size(OBJECT *tree, WORD obj);
WORD fileselect(char *path, char *name,
    WORD *button, char *title);
WORD exist(char *file);
WORD get_cookie(ULONG cookie, ULONG *value);
#define MIN(a, b) ((a) < (b) ? (a) : (b))

/* Globale Variablen */
ULONG   ram;
WORD    magic_pack[1280],
        rbuts[] = {RAM512K, RAM1MB,
            RAM2MB, RAM4MB},
        volume,
        char_w, char_h;
char    path[129];

WORD main(void)
{
    WORD    old_ltatten,
            old_rtatten,
            button,
            end = 0,
            i, j,
            dummy;
    ULONG   _mch = 0;
    
    if (appl_init() < 0)
        return(0);
    /* Resourcen skalieren */
    rsrc_init();
    /* Testen, ob Rechner ein F030 ist */
    if ((!get_cookie('_MCH', &_mch)) || (_mch < 0x30000L))
    {
        form_alert(1, NOFALCON);
        appl_exit();
        return(0);
    }
    /* Testen, ob Multitasking-AES laufen */
    if (_GemParBlk.global[1] != 1)
    {
        form_alert(1, STOSONLY);
        appl_exit();
        return(0);
    }
    graf_mouse(ARROW, NULL);
    graf_handle(&char_w, &char_h, &dummy, &dummy);
    /* Aktuellen Pfad holen */
    sprintf(path, "%c:", (char)(Dgetdrv() + 65));
    Dgetpath(&path[2], 0);
    strcat(path, "\\*.PRG");
    /* Ramgr”že des F030 und aktuelle Einstellungen holen */
    ram = (ULONG)Supexec(get_settings);
    /* Feststellen, welche Ramgr”že maximal genommen werden darf */
    for (i = 3; (ram <= ramsizes[i]) && (i > 1); i--)
    {
        MAINDIAL[rbuts[i]].ob_state |= DISABLED;
        MAINDIAL[rbuts[i] + 1].ob_state |= DISABLED;
    }
    /* Feststellen, welche Ramgr”že mindestens genommen werden muž */
    /* (wegen Magic Pack) */
    for (j = 0; (ULONG)magic_pack >=
        ramsizes[j]; j++)
    {
        MAINDIAL[rbuts[j]].ob_state |= DISABLED;
        MAINDIAL[rbuts[j] + 1].ob_state |= DISABLED;
    }
    /* Abbruch, wenn Mindeswert > Maximalwert */
    if (j > i)
    {
        form_alert(1, NORAM);
        appl_exit();
        return(0);
    }
    /* Aktuelle Einstellungen in Dialog eintragen */
    MAINDIAL[rbuts[i]].ob_state |= SELECTED;
    volume = 15 - (WORD)(MIN((old_ltatten =
        (WORD)soundcmd(LTATTEN, -1)),
        old_rtatten = (WORD)soundcmd(RTATTEN, -1)) / 16);
    set_atten(0);
    MAINDIAL[DCACHE].ob_state = (settings[_DATACACHE] *
        CROSSED) | SELECTED;
    MAINDIAL[ICACHE].ob_state = (settings[_INSTCACHE] *
        CROSSED) | SELECTED;
    MAINDIAL[CPU8MHZ].ob_state = (settings[_CPU8MHZ] *
        CROSSED) | SELECTED;
    MAINDIAL[BLIT8MHZ].ob_state = (settings[_BLIT8MHZ] *
        CROSSED) | SELECTED;
    MAINDIAL[STEBUS].ob_state = (settings[_BUSMODE] *
        CROSSED) | SELECTED;
    MAINDIAL[SPEAKER].ob_state = (settings[_SPEAKER] *
        CROSSED) | SELECTED;
    MAINDIAL[TIMERA].ob_state = (settings[_TIMERA] *
        CROSSED) | SELECTED;
    MAINDIAL[MFPI7].ob_state = (settings[_MFPI7] *
        CROSSED) | SELECTED;
    MAINDIAL[SCRADR].ob_state |= CROSSED;
    do
    {
        /* Dialog bearbeiten */
        if ((button = do_dialog(MAINDIAL,
            0, handle_maindial)) != OK)
        {
            if (button == ABBRUCH)
            {
                /* Lautst„rke auf alten Wert zurcksetzen */
                soundcmd(LTATTEN, old_ltatten);
                soundcmd(RTATTEN, old_rtatten);
                end = 1;
            }
            else
            {
                /* Das Feld settings entsprechend den Einstellungen */
                /* Dialog belegen */
                put_settings();
                /* Speicherroutine aufrufen */
                save();
            }
        }
        else
        {
            /* settings-Feld belegen */
            put_settings();
            /* Booten oder šbernehmen? */
            if (form_alert(1, BOOTEN) == 1)
                boot();
            else
                end = take_settings();
        }
    } while (!end);
    /* Programm abmelden und tschž */
    appl_exit();
    return(0);
}

/* Hier werden die Miniprogramme gespeichert */
void save(void)
{
    WORD    cont,
            i;
    char    title[41], name[129];
    
    /* Welcher Miniprogrammtyp soll's denn sein? */
    cont = do_dialog(SAVEDIAL, 0, handle_savedial);
    if (cont != SAVEOK)
        return;
    if (SAVEDIAL[BOOTPRG].ob_state & SELECTED)
    {
        /* Warnung ausgeben, wenn 1 MB-Rechner mit 1 MB konfiguriert */
        /* werden soll, weil dabei der PMMU-Baum nicht geschtzt */
        /* werden kann */
        if ((ram <= 0x100000LU) &&
            settings[_RAMCONFIG])
        {
            if (settings[_SCRBASE])
                cont = (do_dialog(WARNING1, 0, 0L) == W1OK);
            else
                cont = (do_dialog(WARNING4, 0, 0L) == W4OK);
            if (!cont)
                return;
        }
        /* Programmtyp "mini1" speichern */
        if (do_save(mini1, sizeof(mini1)))
            form_alert(1, DISKERR);
    }
    else
    {
        /* Warnung ausgeben, daž bei Programmen, die nicht booten */
        /* sollen, die Ramkonfiguration unbercksichtigt bleibt */
        /* und somit kein sicherer Platz fr den PMMU-Baum da ist */
        cont = (do_dialog(WARNING2, 0, 0L)
            == W2OK);
        if (!cont)
            return;
        /* Soll das Einstellprogramm ein Programm nachladen? */
        if (form_alert(1, LOADONE) == 1)
        {
            /* Wenn ja, welches? */
            sprintf(name, "");
            sprintf(title, "Nachzuladendes Programm w„hlen!");
            if (fileselect(path, name, &cont, title))
            {
                if (!cont)
                    return;
                for (i = 0; ((WORD *)mini2)[i]
                    != (WORD)0xabce; i++);
                strcpy(&mini2[--i * 2], name);
            }
            else
                return;
        }
        /* Programmtyp "mini2" speichern */
        if (do_save(mini2, sizeof(mini2)))
            form_alert(1, DISKERR);
    }
}

/* Routine zum Schreiben eines Miniprogramms */
WORD do_save(char *rout, LONG size)
{
    WORD    i, j,
            handle,
            save;
    char    name[129], title[41];
    
    /* Werte aus settings-Feld in Programm eintragen */
    for (i = 0; ((WORD *)rout)[i] != (WORD)0xabdc; i++);
    for (j = 0; j < 11; j++)
        ((WORD *)rout)[++i] = settings[j];
    /* Gewnschten Namen erfragen */
    sprintf(title, "Name des Miniprogramms w„hlen!");
    sprintf(name, "");
    if (fileselect(path, name, &save, title))
        if (save)
        {
            /* Nachfragen, ob ein existierendes File berschrieben */
            /* werden soll */
            if (exist(name))
            {
                if (form_alert(1, FEXISTS) == 2)
                    return(0);
            }
            /* Datei anlegen und Routine hineinschreiben */
            handle = (WORD)Fcreate(name, 0);
            if (handle < 0)
                return(1);
            Fwrite(handle, size, (void *)rout);
            Fclose(handle);
        }
    return(0);
}

/* Magic Pack anlegen und Reset ausl”sen */
void boot(void)
{
    WORD    i, j,
            sum,
            first,
            cont,
            checkpos,
            pos;
    LONG    help;
    
    /* Warnung ausgeben, wenn 1 MB-Rechner mit 1 MB konfiguriert */
    /* werden soll, weil dabei der PMMU-Baum nicht geschtzt */
    /* werden kann */
    if ((ram <= 0x100000LU) &&
        settings[_RAMCONFIG])
    {
        if (settings[_SCRBASE])
            cont = (do_dialog(WARNING1, 0, 0L) == W1OK);
        else
            cont = (do_dialog(WARNING4, 0, 0L) == W4OK);
         if (!cont)
            return;
    }
    /* Warnung vor Reset */
    if (form_alert(1, RESET) == 2)
        return;
    /* Startadresse der GEMDOS-Routine fr die alte Bildschirmadresse */
    /* und des PMMU-Baums bestimmen */
    if (ramsizes[settings[_RAMCONFIG]] == ram)
    {
        gdrout = (WORD *)0x600L;
        rootpointer[1] = 0x700L;
        if (!Super((void *)1L))
            Super(0L);
    }
    else
    {
        gdrout = (WORD *)(ram - 256LU);
        rootpointer[1] = ram - 512LU;
    }
    /* PMMU-Baum kopieren */
    for (i = 0; i < 64; i++)
    {
        if ((new_pmmu_tree[i] / 65536LU) ==
            0xffffLU)
        {
            /* Bei entsprechend gekennzeichnetem Eintrag den richtigen */
            /* Offset berechnen */
            new_pmmu_tree[i] =
                rootpointer[1] +
                (new_pmmu_tree[i] & 65535LU);
        }
        else
        {
            /* Sollen Daten- und Befehlscache ausgeschaltet werden, im */
            /* PMMU-Baum Cache-Inhibit-Flag setzen */
            if (!settings[_DATACACHE] &&
                !settings[_INSTCACHE])
            {
                new_pmmu_tree[i] |= 64LU;
            }
        }
        ((LONG *)rootpointer[1])[i] =
            new_pmmu_tree[i];
    }
    /* GEMDOS-Routine kopieren (egal, ob sie gebraucht wird, oder nicht */
    for (i = 0; _gemdos[i] != (WORD)0xabcd; i++)
        gdrout[i] = _gemdos[i];
    gdrout += 6L;
    /* Beginn des Magic Pack bestimmen (muž auf 512-Byte-Grenze fallen) */
    /* Die Magic Packs sind brigens offiziell nicht dokumentiert, sie */
    /* sollten also nur sehr selten benutzt werden */
    help = (LONG)magic_pack;
    if (help % 512L)
        help += 512L - (help % 512L);
    first = pos = (WORD)((help - (LONG)magic_pack) / 2L);
    /* Erster Long-Wert im Magic Pack muž 0x12123456 sein */
    magic_pack[pos++] = 0x1212;
    magic_pack[pos++] = 0x3456;
    /* Im zweiten Long-Wert muž die Anfangsadresse des Packs stehen */
    magic_pack[pos++] = (WORD)(help >> 16);
    magic_pack[pos++] = (WORD)(help & 65535L);
    /* Assembler-Routine kopieren */
    for (i = 0; mpack[i] != (WORD)0xabcd; i++)
        magic_pack[pos + i] = mpack[i];
    /* 16-Bit-Prfsumme ber den Magic Pack bilden */
    for (j = sum = 0; j < 256; sum += magic_pack[first + j++]);
    checkpos = (pos << 1) +
        (WORD)((LONG)&checksum - (LONG)mpack);
    /* Checksumme so „ndern, daž die Prfsumme 0x5678 ergibt (sonst */
    /* wird der Magic Pack nicht ausgefhrt) */
    magic_pack[checkpos >> 1] += (0x5678 - sum);
    /* Reset ausl”sen */
    Supexec(reset);
}

/* Einstellungen direkt bernehmen */
WORD take_settings(void)
{
    WORD goon;
    
    /* Warnung ausgeben, daž beim šbernehmen die Ramkonfiguration */
    /* nicht bercksichtigt wird und daher auch der PMMU-Baum nicht */
    /* gesichert werden kann. Aužerdem bleibt die alte Bildschirm- */
    /* adresse, falls gewnscht, hier nur bis zum n„chsten Aufl”- */
    /* sungswechsel per Desktop erhalten */
    if (settings[_SCRBASE])
    {
        /* Alte Bildschirmadresse ist nur bei aktiven ST-Modus m”glich */
        if (!(Vsetmode(-1) & STMODES))
        {
            form_alert(1, NOSTMODE);
            return(0);
        }
        goon = (do_dialog(WARNING3, 0, 0L)
            == W3OK);
    }
    else
    {
        goon = (do_dialog(WARNING2, 0, 0L)
            == W2OK);
    }
    /* Einstellroutine aufrufen */
    if (goon)
        Supexec(set);
    return(goon);
}

/* Einstellungen aus dem Dialog in das Feld settings bernehmen */
void put_settings(void)
{
    WORD i;
    
    settings[_DATACACHE] = 0x3100 *
        !(!(MAINDIAL[DCACHE].ob_state & CROSSED));
    settings[_INSTCACHE] = 0x11 *
        !(!(MAINDIAL[ICACHE].ob_state & CROSSED));
    for (i = 0; i < 4; i++)
    {
        if (MAINDIAL[rbuts[i]].ob_state & SELECTED)
        {
            settings[_RAMCONFIG] = i;
            break;
        }
    }
    settings[_CPU8MHZ] =
        !(MAINDIAL[CPU8MHZ].ob_state & CROSSED);
    settings[_BLIT8MHZ] = 4 *
        !(MAINDIAL[BLIT8MHZ].ob_state & CROSSED);
    settings[_BUSMODE] = 32 *
        !(MAINDIAL[STEBUS].ob_state & CROSSED);
    settings[_SPEAKER] = 64 *
        !(MAINDIAL[SPEAKER].ob_state & CROSSED);
    settings[_SCRBASE] =
        MAINDIAL[SCRADR].ob_state & CROSSED;
    settings[_TIMERA] =
        !(!(MAINDIAL[TIMERA].ob_state & CROSSED));
    settings[_MFPI7] =
        !(!(MAINDIAL[MFPI7].ob_state & CROSSED));
    settings[_VOLUME] = (15 - volume) * 16;
}

/* Lautst„rke einstellen */
void set_atten(WORD redraw)
{
    WORD x, y, w, h;
    
    MAINDIAL[VOLUME].ob_x = volume * char_w;
    sprintf(MAINDIAL[VOLUME].ob_spec.tedinfo->te_ptext,
        "%d", volume);
    /* Soll der Slider neu gezeichnet werden? */
    if (redraw)
    {
        objc_offset(MAINDIAL, SLIDER, &x, &y);
        w = MAINDIAL[SLIDER].ob_width;
        h = MAINDIAL[SLIDER].ob_height;
        objc_draw(MAINDIAL, SLIDER, 1,
                    x, y, w, h);
    }
    /* Wenn der "Live"-Button gew„hlt ist, die Lautst„rke auch */
    /* tats„chlich aktivieren */
    if (MAINDIAL[LIVE].ob_state & CROSSED)
    {
        soundcmd(LTATTEN, (15 - volume) * 16);
        soundcmd(RTATTEN, (15 - volume) * 16);
    }
}

/* Universelle Dialogverwaltungsroutine, ruft nach solange nach jedem */
/* form_do action auf, bis dieses 0 zurckgibt */
WORD do_dialog(OBJECT *tree, WORD sobj,
    WORD (*action)(OBJECT *tree, WORD obj))
{
    WORD    x, y, w, h,
            cont,
            obj;

    wind_update(BEG_UPDATE);
    wind_update(BEG_MCTRL);
    /* Gr”že der "billigen" Checkboxen und Radiobuttons anpassen */
    /* (billig deswegen, weil ohne G_USERDEF-Objekte gearbeitet */
    /* wird) */
    tree_walk(tree, 0, adapt_size);
    /* Dialog zentrieren und zeichnen */
    form_center(tree, &x, &y, &w, &h);
    form_dial(FMD_START, x, y, w, h, x, y, w, h);
    objc_draw(tree, ROOT, MAX_DEPTH,
        x, y, w, h);
    do
    {
        /* Dialog bearbeiten, und ggf. die bergebene Reaktionsroutine */
        /* aufrufen */
        obj = form_do(tree, sobj);
        if (action != NULL)
            cont = (*action)(tree, obj);
        else
            cont = 0;
    } while (cont);
    /* Wenn das letzte Objekt noch selektiert ist, den Status zurck- */
    /* setzen */
    if ((tree[obj].ob_flags & SELECTABLE) &&
        (tree[obj].ob_state & SELECTED))
    {
        tree[obj].ob_state &= ~SELECTED;
    }
    /* Dialog beenden und zuletzt gew„hltes Objekt zurckgeben */
    form_dial(FMD_FINISH, x, y, w, h, x, y, w, h);
    wind_update(END_MCTRL);
    wind_update(END_UPDATE);
    return(obj);
}

/* Routine, die auf das Anklicken eines Objektes im Speichern-Dialog */
/* reagiert. Wird von do_dialog aufgerufen */
WORD handle_savedial(OBJECT *tree, WORD obj)
{
    /* Doppelklick-Bit entfernen */
    obj &= 0x7fff;
    /* Auf das Anklicken des Radiobutton-Textes reagieren */
    if (tree[obj].ob_type == G_STRING)
        cross(tree, obj - 1);
    /* Rckgabewert 0, wenn "Speichern" oder "Abbruch" angeklickt */
    /* wurde (do_dialog wird dadurch beendet) */
    return(!(tree[obj].ob_flags & EXIT));
}

/* Routine zum Verwalten des Hauptdialogs, wird von do_dialog aufgerufen */
WORD handle_maindial(OBJECT *tree, WORD obj)
{
    WORD    raw,
            x, y, w, h,
            old_volume,
            dummy,
            x2, y2;
    
    /* Doppelklick-Bit merken und entfernen */
    raw = obj;
    obj &= 0x7fff;
    /* Nur etwas machen, wenn angeklicktes Objekt nicht dekativiert war */
    /* (form_do bzw. intern form_button hat da je nach Objekttyp so */
    /* seine Probleme) */
    if (!(tree[obj].ob_state & DISABLED))
    {
        /* Wenn es ein Radiobutton- oder Checkbox-Text war, den */
        /* dazugeh”rigen Button bearbeiten */
        if (tree[obj].ob_type == G_STRING)
            cross(tree, obj - 1);
        /* Checkboxen ankreuzen, wenn sie angeklickt wurden */
        if (tree[obj].ob_type == (0xfe00|G_BOX))
            cross(tree, obj);
        /* Verschieben des Sliders, wenn das Lautst„rke-Feld angeklickt */
        /* wurde */
        if (obj == VOLUME)
        {
            objc_offset(tree, VOLUME,
                &x, &y);
            w = tree[SLIDER].ob_width;
            h = tree[SLIDER].ob_height;
            objc_offset(tree, SLIDER,
                &x2, &y2);
            graf_dragbox(tree[VOLUME].ob_width,
                tree[VOLUME].ob_height,
                x, y, x2, y2, w, h,
                &x, &y);
            volume = (x - x2) / char_w;
            set_atten(1);
        }
        /* Wurde auf den Sliderhintergrund geklickt, entsprechend */
        /* reagieren */
        if (obj == SLIDER)
        {
            wind_update(BEG_MCTRL);
            graf_mkstate(&x, &y, &dummy, &dummy);
            objc_offset(tree, VOLUME, &x2, &y2);
            do
            {
                old_volume = volume;
                if (x < x2)
                {
                    if (volume >= 3)
                        volume -= 3;
                    else
                        volume = 0;
                }
                else
                {
                    if (volume <= 12)
                        volume += 3;
                    else
                        volume = 15;
                }
                if (old_volume != volume)
                {
                    set_atten(1);
                    evnt_timer(80, 0);
                }
            } while (!(evnt_multi(MU_TIMER|MU_BUTTON, 1, 1, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, 1, 0,
                &x, &y, &dummy, &dummy, &dummy, &dummy) &
                MU_BUTTON));
            wind_update(END_MCTRL);
        }
        /* Bei den Auf- bzw. Ab-Pfeilen die Lautst„rke um eins erh”hen */
        /* bzw. verringern. Bei Doppelklick auf 15 bzw. 0 setzen */
        if ((obj == UP) && (volume < 15))
        {
            if (obj != raw)
                volume = 15;
            else
                volume++;
            set_atten(1);
            evnt_timer(80, 0);
        }
        if ((obj == DOWN) && volume)
        {
            if (obj != raw)
                volume = 0;
            else
                volume--;
            set_atten(1);
            evnt_timer(80, 0);
        }
    }
    /* 0 zurckgeben, wenn ein Button mit gesetzen Exit-Flag gew„hlt */
    /* wurde (OK, Abbruch oder Speichern). do_dialog wird dadurch */
    /* beendet */
    return(!(tree[obj].ob_flags & EXIT));
}

/* Checkboxen ankreuzen oder Radiobuttons invertieren (letzteres wird */
/* dann gebraucht, wenn nur der Text des Buttons gew„hlt wurde) */
void cross(OBJECT *tree, WORD obj)
{
    WORD    x, y, w, h,
            draw = 1,
            dummy;
    
    objc_offset(tree, obj, &x, &y);
    w = tree[obj].ob_width;
    h = tree[obj].ob_height;
    /* Bei Radiobutton form_button aufrufen, sonst den Ankreuz-Status */
    /* invertieren */
    if (tree[obj].ob_flags & RBUTTON)
    {
        form_button(tree, obj, 1, &dummy);
        draw = 0;
    }
    else
        tree[obj].ob_state ^= CROSSED;
    /* Ggf. Objekt neuzeichnen */
    if (draw)
    {
        objc_draw(tree, obj, 0, x, y, w, h);
        evnt_button(1, 1, 0, &dummy, &dummy,
            &dummy, &dummy);
    }
}

/* Routine zum Durchwandern des Objektbaumes tree, ab Objekt start. */
/* Bei jedem Objekt wird action aufgerufen, wenn action 0 zurckgibt, */
/* wird abgebrochen */
WORD tree_walk(OBJECT *tree, WORD start,
    WORD (*action)(OBJECT *tree, WORD obj))
{
    WORD    i,
            cont;
    
    for (i = tree[start].ob_head, cont = 1;
        (i != start) && (i != -1) && cont;
        i = tree[i].ob_next)
    {
        cont = (*action)(tree, i);
        if (cont)
            cont = tree_walk(tree, i, action);
    }
    return(cont);
}

/* Routine zum Anpassen der Gr”žen von Radiobuttons und Checkboxen, wird */
/* von tree_walk aufgerufen */
WORD adapt_size(OBJECT *tree, WORD obj)
{
    if (tree[obj].ob_type == (0xff00 | G_BOX))
    {
        tree[obj].ob_width--;
        tree[obj].ob_height--;
        tree[obj].ob_type = 0xfe00|G_BOX;
    }
    return(1);
}

/* Universelle Fileselektor-Routine, gleiche Parameter wie bei */
/* fsel_exinput. name enth„lt nachher allerdings den kompletten */
/* Pfadnamen, nicht nur den Namen selbst, deshalb gengend Platz */
/* fr name reservieren. Es wird automatisch geprft, ob fsel_exinput */
/* aufgerufen werden kann. Aužerdem wird eine Meldung ausgegeben, wenn */
/* fsel_(ex)input einen Fehler gemeldet hat. */
WORD fileselect(char *path, char *name, WORD *button, char *title)
{
    char    temp1[129], temp2[129];
    WORD    i, fsel_ok;
    
    /* Prfen, ob fsel_exinput aufgerufen werden kann, dabei wird auch */
    /* der FSEL-cookie geprft, der z.B. von SELECTRIC angelegt wird */
    if (((_GemParBlk.global[0] >= 0x0140) &&
        (_GemParBlk.global[0] < 0x0200)) ||
        (_GemParBlk.global[0] >= 0x0300) || get_cookie('FSEL', 0L))
    {
        fsel_ok = fsel_exinput(path, name, button, title);
    }
    else
        fsel_ok = fsel_input(path, name, button);
    
    if (fsel_ok)
    {
        /* Wurde OK geklickt, kompletten Zugriffspfad fr name */
        /* zusammensetzen */
        if (*button)
        {
            strcpy(temp1, path);
            
            i = (WORD)strlen(temp1) - 1;
            
            while ((temp1[i] != '\\') && (i >= 0))
                temp1[i--] = 0;
            
            strcpy(temp2, name);
            strcpy(name, temp1);
            strcat(name, temp2);
        }
    }
    else
    {
        form_alert(1, "[3][Fehler bei Dateiauswahl|aufgetreten!]"
                    "[Abbruch]");
    }
    return(fsel_ok);
}

/* šberprfen, ob bergebenes File existiert (Rckgabewert 1), oder */
/* nicht (Rckgabewert 0) */
WORD exist(char *file)
{
    DTA     disk_buf;
    WORD    ret;

    graf_mouse(BUSYBEE, 0L);
    
    Fsetdta(&disk_buf);
    ret = !Fsfirst(file, 0x17);
    
    graf_mouse(ARROW, 0L);
    
    return(ret);
}

/* šberprft, ob der Cookie cookie vorhanden ist und schreibt dessen */
/* Wert dann in value. Rckgabewert 0, wenn der Cookie nicht vorhanden */
/* ist, sonst 1 */
WORD get_cookie(ULONG cookie, ULONG *value)
{
    LONG    *jar,
            old_stack;
    
    if (Super((void *)1L) == 0L)
    {
        old_stack = Super(0L);
        jar = *((LONG **)0x5a0L);
        Super((void *)old_stack);
    }
    else
        jar = *(LONG **)0x5a0;
    
    if (jar == 0L)
        return(0);
    
    while (jar[0])
    {
        if (jar[0] == cookie)
        {
            if (value != 0L)
                *value = jar[1];
            
            return(1);
        }
        
        jar += 2;
    }
    return(0);
}
/* Modulende */
