'Installationsprogramm
'
// *************************************************************
//      GFA-BASIC für Windows Demonstrations-Programm
//      Copyright (c) 1995 by GFA Systemtechnik GmbH
//      (solange kein anderer Copyright-Inhaber genannt ist)
// -------------------------------------------------------------
//      Sie dürfen dieses Programm kopieren, editieren
//      und verbreiten, so lange Sie auf den Copyright-
//      Halter verweisen und das Demo nicht als Ihr
//      eigenes Programm verkaufen.
//      Es ist Ihnen gestattet, Teile dieses Programms
//      für eigene Zwecke zu verwenden, wenn das
//      Ergebnis dem Original nicht in Aussehen und
//      Funktionalität ähnelt.
//      Dieses Programm dient dazu, die Verwendung
//      von GFA-BASIC und der Windows-API-Funktionen
//      zu demonstrieren.
//      Erweiterungen sollten dokumentiert und in die
//      GFA-Mailbox in Deutschland oder den GFA-Be-
//      reich in CompuServe upgeloadet werden. Beide
//      Einrichtungen bieten Ihnen weitere Beispiel-
//      Programme, Support und Demo-Versionen von
//      GFA-BASIC.
// **************************************************************
// **************************************************************
//      GFA-BASIC for Windows Demonstration Program
//      Copyright (c) 1995 by GFA Systemtechnik GmbH
//      (if no other copyright holder is specified)
// --------------------------------------------------------------
//      You may copy, edit and distribute this program
//      freely as long as you give credit and do not sell
//      this demo as your own program.
//      You are allowed to use parts of the demo for your
//      own needs if the result does not be similar to the
//      original concerning outfit and functionality.
//      The purpose of this program is to demonstrate
//      the use of GFA-BASIC and the Windows API.
//      Enhancements should be documented and up-
//      loaded to the GFA BBS in Germany or to the GFA
//      section in CompuServe. Both services offer you
//      more examples, support and demo versions of
//      GFA-BASIC.
// **************************************************************
//      GFA BBS Germany, Moenchengladbach:
//              +49-2161-482460,24h,8N1,14400 bps, v.terbo
// **************************************************************
//      GFA CompuServe
//              GO WINAPC, section GFA
//              GFA CIS-ID: 75300,3224
// ***************************************************************
//      Last revision: 11/95 by F. Rode, for GFA Germany
//      Written by STSOFT in Aug 1995
// ***************************************************************

// Ein Installationsprogramm

/*$LNK res "c:\windows\gfawin\install\install.res"  /* Compiler
$DESCR DataBasics Installer                         /* Befehle
OPENW #1,0,0,_X,_Y,16+64+32
/* Fenster auf mit Titelleiste,Schließfeld und Minimizerfeld
TITLEW #1,"DataBasics Installation Utility V1.0" /* Titelstring anzeigen
FONT "MS Sans Serif",HEIGHT 16,WIDTH 0,WEIGHT FW_NORMAL /* Font-
/* Parameter deklarieren
FONT ORIENTATION 0,ESCAPEMENT 0,ITALIC 0,STRIKEOUT 0,UNDERLINE 0
FONT QUALITY 0,FAMILY FF_ROMAN,PITCH VARIABLE_PITCH,CHARSET ANSI_CHARSET
FONT TO fntMSans& /* Handle auf Fontstruktur
GRAPHMODE ,OPAQUE /* Zeichenmodus, Hintergrund deckend
t1$ = "Initialising Setup Please Wait..."       /* String deklarieren
DIALOG #0,(_X-300)/2,170,280,50,"",$80400002,-15,"MS Sans Serif"
  /* Dialogstruktur und Control für 'Splash' Screen' erstellen
  CONTROL t1$,100,"static",$10000001,2,12,270,50
ENDDIALOG
DLG FILL 0,RGB(192,192,192)     /* Dlg einfärben
SHOWDIALOG #0                   /* und anzeigen
FOR n% = 1 TO 100               /* 'Warteschleife' mit 100
  PEEKEVENT                     /* Nachrichtenabfragen
NEXT n%
color% = SYSCOL(2)                /* Farbe Titelzeile?
DIM filename$(300),filesize%(300),filedir$(300)/* Array's definieren
DLG FILL 0,RGB(192,192,192)     /* DLG Hintergrund hellgrau
OPTION BASE 1   /* Zeilenoffset für Felder festlegen
windir$ = @getwindir$   /* div. Unterprogramme
@Sys_Info
a& = 1
@Call_Screen(a&)
CLOSEDIALOG #0          /* DLG#0 schließen
WIN #1                  /* Ausgabe auf Fenster#1 umschalten
FOR n% = 1 TO 100        /* 'Warteschleife'
  PEEKEVENT
NEXT n%
@redrawscreen(TRUE)     /* Unterprogr.
@Dir_Dialog_From
IF e1| = 1              /* wenn...
  IF EXIST(currentdir$ + "setup.ini")     /* wenn Datei existiert
    @Read_Ini                           /* verzweige
  ELSE                                  /* sonst
    ALERT 1,"SETUP.INI File Not Found.|Unable to Continue.",1,"E&xit",k&
    /* Fehlermeldung
    CLOSEW #1   /* Fenster zu
    END         /* Progr.Ende
  ENDIF
ELSE            /* wenn nicht...
  CLOSEW #1     /* Fenster zu
  END           /* Progr.Ende
ENDIF
IF wver >= VAL(winversion$)     /* wenn Windowsversion....
  @Dir_Dialog_To                /* Unterprogramme
  IF e| = 1                     /* wenn e|...
    @Check_Disk_Space
    @Test_Install_Dir
    FOR i& = 1 TO dnum&
      @Test_Sub_Dir
    NEXT i&
    IF NOT EXIST(LEFT$(installdirto$,3)+"DB LOCK.INF")
      /* wenn Datei nicht existiert
      OPEN "o",#1,LEFT$(installdirto$,3)+"DB LOCK.INF"
      /* dann erstellen
      FOR n = 1 TO 1000+RND(500)
        x=RND(255)
        OUT #1,x        /* Dummywerte in Datei schreiben
      NEXT n
      CLOSE #1          /* und schließen
    ENDIF
    @Install_Files      /* weitere Unterprogramme aufrufen
    IF auto$ = "AUTOEXEC = YES" THEN @Change_Autoexec
    IF conf$ = "CONFIG = YES" THEN @Change_Config
    IF wini$ = "WIN INI = YES" THEN @Change_Win
    IF oth$ = "OTHER = YES" THEN @Change_Other
    @End_Main
    @init_dde
    create_group(groupname$,"")
    show_group (groupname$,1)
    FOR z& = 1 TO itemnum&
      IF LEN(itemname$(z&)) > 1         /* wenn Stringlänge....
        IF LEFT$(copydir$(z&),1) = "\"    /* wenn Teilstring ...
          add_item (LEFT$(installdirto$,2)+copydir$(z&)+iteminstall$(z&),itemname$(z&),"",0,0,0,"","",0)
          /* Unterprogramm
        ELSE                            /* wenn Teilstring nicht....
          add_item (installdirto$+"\"+copydir$(z&)+iteminstall$(z&),itemname$(z&),"",0,0,0,"","",0)
          /* Unterprogramm
        ENDIF
      ENDIF
    NEXT z&
    exit_progman ("0")
    @kill_dde
  ENDIF
ELSE    /* wenn e| nicht...
  ALERT 1,"Unable to Install to this|Version of Windows....",1,"&Close",a&
  /* Fehlermeldung
ENDIF
a& = 2
@Call_Screen(a&)
CLOSEW #1       /* Fenster zu
> PROCEDURE Call_Screen(VAR a&)
  IF a& = 1                                     /* wenn...
    grad& = LOADBMP(currentdir$ + "grad.rle")       /* dann Bmp's laden
    logo& = LOADBMP(currentdir$+"vga.rle")
  ENDIF
  IF a& = 2             /* wenn....
    FREEBMP logo&       /* Speicher freigeben
    FREEBMP grad&
  ENDIF
RETURN
> PROCEDURE getnextdialog(filename$)
  LOCAL text$,found!,file$      /* nur in Proc gültig
  file$ = installdirfrom$ + "dialog.txt"    /* String erstellen
  IF EXIST(file$)       /* wenn Datei existiert
    OPEN "i",#4,file$   /* Datei öffnen
    REPEAT              /* Schleife
      LINE INPUT #4,text$       /* Zeichenkette einlesen
      IF LEFT$(text$,1)="#" AND TRIM$(MID$(text$,2))=UPPER$(TRIM$(filename$))
        /* Teilstring suchen
        found! = TRUE     /* gefunden
        IF message$ <> "" THEN    /* wenn String nicht leer
          @infodialog(FALSE)    /* Unterprogramm aufrufen
          message$ = ""           /* Leerstring
        ENDIF
        REPEAT                  /* Schleife
          LINE INPUT #4,text$   /* Zeichenkette einlesen
          IF LEFT$(text$,1) <> "#"/* wenn Teilstring nicht "#"
            message$ = message$ + text$ /* String zusammenstellen
          ENDIF
        UNTIL LEFT$(text$,1)="#" OR EOF(#4)=TRUE
        /* raus aus Schleife wenn Teilstring="#" oder Dateiende erreicht
        @infodialog(TRUE)
        WIN #2  /* umschalten auf Fenster#2
      ENDIF
    UNTIL EOF(#4)=TRUE OR found!=TRUE
    /* raus aus Schleife wenn Dateiende oder found|=TRUE
    CLOSE #4    /* Datei schließen
  ENDIF
RETURN
> PROCEDURE drawmeter /* 3D Darstellung zeichnen
  COLOR 0,247
  DRAW 378,21 TO 378,99 TO 21,99
  DRAW 21,153 TO 21,119 TO 379,119
  DRAW 21,100 TO 21,21 TO 379,21
  COLOR 255,0
  DRAW 379,119 TO 379,153 TO 21,153
  BOX 22,22,379,100
  COLOR 0,7
  TEXT 150,3,"Copying Files"
  RGBCOLOR color%,RGB(192,192,192)
  FOR n%=3 TO 0 STEP -1
    BOX 0+n%,0+n%,397-n%,171-n%
  NEXT n%
  TEXT 25,23,"From:"
  TEXT 25,62,"To:"
RETURN
> PROCEDURE metertext     /* Texte ausgeben
  COLOR 7,7
  TEXT 25, 42,UPPER$(oldfrom$)
  TEXT 25, 81,UPPER$(oldto$)
  COLOR 0,7
  TEXT 25, 42,UPPER$(from$)
  TEXT 25, 81,UPPER$(to$)
  oldfrom$=from$
  oldto$=to$
RETURN
> PROCEDURE Meter(percent&)       /* Fortschrittsbalken zeichnen
  WIN #2
  IF percent& <=100
    COLOR 0,247
    offset& = (358 * percent&)/100 + 20
    IF offset& > 20
      RGBCOLOR color%
      PBOX 20,119,offset&,153
      COLOR 255,0
      DRAW 19,119 TO offset&,119
      COLOR 0,247
      DRAW offset&,119 TO offset&,153
      DRAW 19,153 TO offset&,153
    ENDIF
    TEXT 200-TXTLEN(STR$(percent&)+"%")/2,102,STR$(percent&)+"%"
    /* % Text ausgeben
  ENDIF
RETURN
> PROCEDURE Sys_Info
  DLL #1,"kernel.dll"           /* DLL öffnen
    DECL DWORD GetHeapSpaces(w) /* Funktion deklarieren
  ENDDLL                        /* Ende DLL Struktur
  currentdir$ = @getdir$        /* current logged directory
  '                             /* aktuelles Verzeichnis
  sysdir$ = @getsysdir$         /* Windows System directory
  '                             /* Windows System Verzeichnis
  wver = @getwinver             /* Windows version number
  '                             /* Windows Version
  cpu = @getcpu                 /* CPU type
  '                             /* CPU Typ
  math$ = @getmathchip$()       /* Co-processor
  '                             /* Co Prozessor
  FREEDLL 1                     /* Dll freigeben
RETURN
> FUNCTION getdir$()      /* aktuelle Dir feststellen
  ~INTR($21,_AH = $19)            /* Interrupt#21 aufrufen
  drive$ = CHR$(65 + _AL)       /* Name Laufwerk auslesen
  drive& = _AL + 65             /* Laufwerknummer aus Register_AL+65
  buffer$ = SPACE$(65)            /* String erstellen
  _DL = ASC(drive$) & 31          /* Register _DL belegen
  _DS = SWAP(V:buffer$)           /* Low/HighWort der Adresse vertauschen
  '                             /* und nach Register _DS
  _SI = V:buffer$                 /* nach _SI die Aresse des Strings
  ~INTR($21,_AH = $47)            /* und Intr aufrufen
  currentdir$ = drive$+":\"+CHAR{V:buffer$}
  currentdir$ = drive$+":\windows\gfawin\install"
  RETURN "a:\"
  /*  RETURN currentdir$            /* Rückgabe aktuelle Dir
ENDFUNC

> FUNCTION getwindir$()
  buff$ = SPACE$(255)     /* String erstellen
  tchars& = GetWindowsDirectory(V:buff$,255)
  /* Windows Verzeichnis auslesen
  windir$ = LEFT$(buff$,tchars&)
  RETURN windir$        /* und zurückgeben
ENDFUNC

> FUNCTION getsysdir$()
  buff$ = SPACE$(255)   /* String erstellen
  tchars& = GetSystemDirectory(V:buff$,255)
  /* Windows System Verzeichnis auslesen
  sysdir$ = LEFT$(buff$,tchars&)
  RETURN sysdir$        /* und zurückgeben
ENDFUNC

> FUNCTION getwinver()
  version& = GetVersion()
  /* Windows Version auslesen
  wver = ((version& MOD 256) * 100) + version& \ 256 /* berechnen
  RETURN wver   /* und zurückgeben
ENDFUNC

> FUNCTION getcpu()
  /* installierte CPU feststellen
  /* durch verknüpfen von flag% mit WF_... wird der CPU Typ bestimmt
  flags% = GetWinFlags()
  match& = 1
  IF (flags% AND WF_CPU486) \ WF_CPU486 THEN
    cpu& = 486
  ELSE IF (flags% AND WF_CPU386) \ WF_CPU386
    cpu& = 386
  ELSE
    cpu& = 286
  ENDIF
  RETURN cpu&
ENDFUNC
> PROCEDURE redrawscreen(logo!)
  /* wenn WM_PAINT Nachricht ansteht
  WIN #1        /* umschalten auf Fenster#1
  PUT 0,0,grad& /* Bmp ausgeben
  IF logo!      /* wenn....
    PUT 105,70,logo&    /* Bmp ausgeben
  ENDIF
RETURN
> FUNCTION getmathchip$()
  /* ist ein Co Prozessor installiert
  flags% = GetWinFlags()
  /* durch verknüpfen von flag% mit WF_... wird der CO Prozessor
  /* bestimmt
  IF flags% AND WF_80x87 THEN
    math$ = "YES"
  ELSE
    math$ = "NO"
  ENDIF
  RETURN math$
ENDFUNC
> PROCEDURE infodialog(open!)
  IF open!              /* wenn...
    DIALOG #5,105,90,425,130,"",$80400002,-15,"MS Sans Serif"
      /* Dialogstruktur und Controls erstellen
      CONTROL "",100,"static",$10000000,50,10,350,130
      CONTROL "",104,"static",$10000007,5,5,405,110
      CONTROL "",105,"static",$10000009,6,6,405,110
      ICON "#1",2,10,10,1,1,SS_ICON
    ENDDIALOG
    DLG FILL 5,RGB(192,192,192) /* DLG Hintergrund einfärben
    _WIN$(DLGITEM(5,100)) = message$  /* Text in Control#100 anzeigen
    SHOWDIALOG #5       /* Dialog anzeigen
    FOR n% = 1 TO 50      /* 'Warteschleife'
      PEEKEVENT         /* mit 50malige Nachrichtenabfrage
    NEXT n%
    WIN #2              /* umschalten auf Fenster#2
    @drawmeter          /* Unterprogramme
    @Meter(percent&)
  ELSE                  /* sonst...
    CLOSEDIALOG #5      /* DLG zu
  ENDIF
RETURN
> PROCEDURE Dir_Dialog_To
  DISABLEW 1
  DIALOG #0,(_X-348)/2,260,348,150,"",$90400002,-15,"MS Sans Serif"
    /* Dialogstruktur und Controls erstellen
    CONTROL "Copy To What Directory?",100,"static",$10000000,20,30,250,20
    CONTROL "",101,"edit",$10810088,20,50,300,25
    CONTROL "&Continue",102,"button",$10010001,20,90,140,30
    CONTROL "E&xit",103,"button",$50000000,180,90,140,30
    CONTROL "",104,"static",$10000007,10,20,320,60
    CONTROL "",105,"static",$10000009,11,21,320,60
  ENDDIALOG
  SHOWDIALOG #0         /* Dialog anzeigen
  _WIN$(DLGITEM(0,101)) = "C:\" + defaultdir$ /* akt. Verzeichnis anzeigen
  ~SetFocus(DLGITEM(0,101))     /* Focus setzen (Control wird aktiviert)
  DO                            /* Schleife
    SLEEP                       /* warte auf Nachricht
    IF MENU(1) = 21               /* wenn WM_PAINT
      @redrawscreen(TRUE)       /* Unterprogr.
    ENDIF
    SELECT MENU(6)              /* welche ID?
    CASE 102                    /* Control#102
      installdirto$ = _WIN$(DLGITEM(0,101))     /* Text auslesen
      e| = 1
    CASE 103                    /* ID#103
      e| = 2
    ENDSELECT
    IF MENU(11) = WM_KEYDOWN    /* wurde Taste gedrückt?
      SELECT MENU(12)           /* _wParam ?
      CASE VK_RETURN            /* wenn ReturnTaste
        installdirto$ = _WIN$(DLGITEM(0,101))  /* Text auslesen
        e| = 1
      CASE VK_ESCAPE            /* wenn EscTaste
        e| = 2
      ENDSELECT
    ENDIF
    EXIT IF e| > 0              /* Schleife verlassen wenn...
  LOOP
  ENABLEW 1                     /* Input Fenster#1 möglich
  CLOSEDIALOG #0                /* Dialog zu
  PEEKEVENT                     /* Nachricht da?
  @redrawscreen(FALSE)          /* Unterprogramm
RETURN
> PROCEDURE Dir_Dialog_From
  DISABLEW 1                    /* kein Input möglich
  DIALOG #0,(_X-348)/2,260,348,150,"",$90400002,-15,"MS Sans Serif"
    /* Dialogstruktur und Controls erstellen
    CONTROL "Copy From Where ?",100,"static",$10000000,20,30,250,20
    CONTROL "",101,"edit",$10810088,20,50,300,25
    CONTROL "&Continue",102,"button",$10010001,20,90,140,30
    CONTROL "E&xit",103,"button",$50000000,180,90,140,30
    CONTROL "",104,"static",$10000007,10,20,320,60
    CONTROL "",105,"static",$10000009,11,21,320,60
  ENDDIALOG
  SHOWDIALOG #0 /* Dialog anzeigen
  _WIN$(DLGITEM(0,101)) = currentdir$   /* akt. Verzeichnis nach Control#101
  ~SetFocus(DLGITEM(0,101))     /* Focus setzen
  DO                            /* Schleife
    SLEEP                       /* warte auf Nachricht
    IF MENU(1) = 21             /* wenn WM_PAINT
      @redrawscreen(TRUE)       /* Unterprogr.
    ENDIF
    SELECT MENU(6)              /* welche Control ID
    CASE 102                    /* #102
      installdirfrom$ = _WIN$(DLGITEM(0,101)) /* Text auslesen
      e1| = 1
    CASE 103                    /* #103
      e1| = 2
    ENDSELECT
    IF MENU(11) = WM_KEYDOWN    /* wurde eine Taste gedrückt?
      SELECT MENU(12)           /* _wParam ?
      CASE VK_RETURN            /* Return Taste
        installdirfrom$ = _WIN$(DLGITEM(0,101)) /* Text auslesen
        e1| = 1
      CASE VK_ESCAPE            /* Esc Taste
        e1| = 2
      ENDSELECT
    ENDIF
    EXIT IF e1| > 0             /* raus hier wenn....
  LOOP
  ENABLEW 1                     /* Input wieder Fenster#1
  CLOSEDIALOG #0                /* Dialog zu
  FOR n% = 1 TO 50               /* 'Warteschleife'
    PEEKEVENT                   /* mit Nachrichtenabfrage
  NEXT n%
  @redrawscreen(TRUE)           /* Unterprogramm
RETURN
> PROCEDURE Test_Install_Dir
  TRY   /* interne Fehlerbehandlung
    MKDIR installdirto$ /* erstelle Verzeichnis
  CATCH /* wenn Fehler, dann hier weiter
  SELECT ERR    /* welcher Fehler
  CASE -13      /* wenn -13 .....
    /*    RMDIR installdirto$
  ENDSELECT
RETURN
> PROCEDURE Test_Sub_Dir
  TRY   /* interne Fehlerbehandlung
    IF LEFT$(dname$(i&),1) = "\" THEN     /* wenn Teilstring '\' dann
      MKDIR LEFT$(installdirto$,2) + dname$(i&) /* Verzeichnis erstellen
    ELSE                                /* sonst
      MKDIR installdirto$ + "\" + dname$(i&)      /* Verzeichnis erstellen
    ENDIF                                     /* '\' in String einfügen
  CATCH  /* wenn Fehler, dann hier weiter
  SELECT ERR    /* welcher Fehler?
  CASE -13      /* wenn ...
    /*RMDIR installdirto$
  ENDSELECT
RETURN
> PROCEDURE Install_Files
  DLL #1,"lzexpand.dll"  /* DLL öffnen
    DECL LONG LZCopy(w,w)/* Funktion deklarieren
  ENDDLL                 /* Ende DLL Struktur
  /* Strings zusammenstellen
  IF math$ = "YES" THEN testsystem$ = STR$(cpu&)+"MATH"
  IF math$ = "NO" THEN testsystem$ = STR$(cpu&)+"N/A"
  percent& = 0
  OPENW #2,118,255,400,174,0    /* Fenster öffnen
  SETFONT fntMSans&             /* Font setzen
  COLOR 7                       /* Farbe setzen
  DEFFILL 0                     /* Füllmuster bestimmen
  CLS 7                         /* Bildschirm mit Farbe 7 löschen
  FOR currentdisk& = 1 TO disk& /* Schleife
    PEEKEVENT                   /* Ereignis überprüfen
    @Read_Info
    IF MENU(1) = 21 THEN          /* wenn WM_PAINT
      @redrawscreen(FALSE)      /* dann Unterprogramme..
      @Meter(percent&)
    ENDIF
    @drawmeter                  /* verschiedene Unterprogramme
    @Meter(percent&)
    @Read_INF
    FOR i& = 1 TO filecount& - 1
      IF type$(i&) = testsystem$ || type$(i&) = "N/A"
        @Copy_File
        percent& = percent& + INT((size% / VAL(dspace$))*100)
        @Meter(percent&)
      ENDIF
    NEXT i&
  NEXT currentdisk&
  percent& = 100
  @Meter(percent&)
  PAUSE 20      /* Pause für n/18.2 sec
  IF message$<>""
    @infodialog(FALSE)
  ENDIF
  FREEDLL 1     /* Dialog freigeben
  CLOSEW #2     /* Fenster zu
  FOR n% = 1 TO 100       /* 'Warteschleife'
    PEEKEVENT
  NEXT n%
  @redrawscreen(TRUE)
RETURN
> PROCEDURE Copy_File
  from$ = UCASE$(installdirfrom$ + filename$(i&)) /* String für QuellDatei
  IF LEFT$(filedir$(i&),1) = "\" THEN     /* Teilstring '\' vorhanden
    to$ = UCASE$(LEFT$(installdirto$,2)+filedir$(i&)+filename$(i&))
    /* String für DestinationDatei erstellen
  ELSE  /* wenn '\' nichtvorhanden
    to$ = UCASE$(installdirto$+"\"+filedir$(i&)+filename$(i&))
    /* dann in String einfügen
  ENDIF
  @getnextdialog(filename$(i&))
  @metertext
  IF NOT EXIST(from$) THEN /* wenn QuellDatei nicht vorhanden
    ALERT 1,"ERROR !! Cannot Locate|Source File :|"+MID$(from$,RINSTR(from$,"\",LEN(from$)-1)+1)+"|File Will Be Skipped...",1," OK ",a
    /* Fehlermeldung
  ELSE  /* wenn QuellDatei vorhanden
    OPEN "i",#1,from$   /* QuellDatei öffnen
    OPEN "o",#2,to$     /* DestDatei erstellen
    size% = LOF(#1)       /* Dateilänge von Datei#1 auslesen
    a% = ^LZCopy(_FILE(1),_FILE(2))/* Inhalt von QuellDatei nach DestDatei
    '                            /* kopieren
    CLOSE #1            /* Datei#1 schließen
    CLOSE #2            /* Datei#2 schließen
  ENDIF
RETURN
> PROCEDURE init_dde
  init_cons()
  ~SendMessage(-1,WM_DDE_INITIATE,w&,MAKELONG(app&,topic&))
  maxwait&=2000
  FOR x&=1 TO maxwait&
    PEEKEVENT
  NEXT x&
  serverw&=pm_hdl&
  ~SendMessage(-1,WM_DDE_ADVISE,w&,MAKELONG(item&,hopt&))
  wait_ack()
RETURN
> PROCEDURE init_cons()
  a$="Program Manager"+CHR$(0)
  pm_hdl&=FindWindow(0,V:a$)
  w&=WIN(1)
  a$="PROGMAN"+CHR$(0)
  t$="PROGMAN"+CHR$(0)
  item$=""
  app&=GlobalAddAtom(a$)
  topic&=GlobalAddAtom(t$)
  item&=GlobalAddAtom(item$)
  IF app&=0 OR topic&=0
    alert()
  ENDIF
RETURN
> PROCEDURE kill_cons()
  ~GlobalAddAtom(app&)
  topic&=GlobalAddAtom(topic&)
  item&=GlobalAddAtom(item&)
RETURN
> PROCEDURE alert
  ALERT 1,"No Server|",1,"Cancel",a&
  CLOSEW #1
  END
RETURN
> PROCEDURE wait_ack()
  i& = 0
  DO
    PEEKEVENT
    INC i&
  LOOP UNTIL MENU(11) = WM_DDE_ACK OR i& > maxwait&
  IF i& => maxwait&
    alert()
  ENDIF
RETURN
> PROCEDURE create_group(gname$,gpath$)
  itemalloc& = GlobalAlloc(GMEM_DDESHARE,100)
  item% = GlobalLock(itemalloc&)
  IF gname$ = ""
    ALERT 1,"CreateGroup ERROR|Bad GroupName",1,"OOPS!!!",alert|
  ELSE
    IF gpath$ <> ""
      gpath$ = ","+gpath$
    ENDIF
    group$ = "[CreateGroup("+gname$+gpath$+")]"+CHR$(0)
    POKE$ item%,group$
    ~PostMessage(serverw&,WM_DDE_EXECUTE,w&,MAKELONG(itemalloc&,0))
    wait_ack()
  ENDIF
  ~GlobalUnlock(itemalloc&)
  ~GlobalFree(itemalloc&)
RETURN
> PROCEDURE delete_group(gname$)
  itemalloc& = GlobalAlloc(GMEM_DDESHARE,100)
  item% = GlobalLock(itemalloc&)
  IF gname$ = ""
    ALERT 1,"DeleteGroup ERROR|Bad GroupName",1,"OOPS!!!",alert|
  ELSE
    group$ = "[DeleteGroup("+gname$+")]"+CHR$(0)
    POKE$ item%,group$
    ~PostMessage (serverw&,WM_DDE_EXECUTE,w&,MAKELONG(itemalloc&,0))
    wait_ack()
  ENDIF
  ~GlobalUnlock(itemalloc&)
  ~GlobalFree(itemalloc&)
RETURN
> PROCEDURE show_group(gname$,cmd%)
  itemalloc& = GlobalAlloc(GMEM_DDESHARE,100)
  item% = GlobalLock(itemalloc&)
  IF cmd% > 8 OR cmd% < 1
    ALERT 1,"ShowGroup ERROR|Bad Command Number",1,"OOPS!!!",alert|
  ELSE
    IF gname$ = ""
      ALERT 1,"ShowGroup ERROR|Bad GroupName",1,"OOPS!!!",alert|
    ELSE
      group$ = "[ShowGroup("+gname$+","+STR$(cmd%)+")]"+CHR$(0)
      POKE$ item%,group$
      ~PostMessage (serverw&,WM_DDE_EXECUTE,w&,MAKELONG(itemalloc&,1))
      wait_ack()
    ENDIF
  ENDIF
  ~GlobalUnlock(itemalloc&)
  ~GlobalFree(itemalloc&)
RETURN
> PROCEDURE add_item(cmd_line$,iname$,ipath$,iindex%,xpos%,ypos%,def_dir$,hotkey$,minimize%)
  itemalloc&=GlobalAlloc(GMEM_DDESHARE,100)
  item%=GlobalLock(itemalloc&)
  IF cmd_line$=""
    ALERT 1,"add_item error|bad command line",1,"ooops",alert|
  ELSE
    IF iname$=""
      ipath$=""
      iindex$=""
      xpos$=""
      ypos$=""
      def_dir$=""
      hotkey$=""
      minimize$=""
    ELSE IF ipath$=""
      iname$=","+iname$
      iindex$=""
      xpos$=""
      ypos$=""
      def_dir$=""
      hotkey$=""
      minimize$=""
    ELSE IF xpos%<=0
      iname$=","+iname$
      ipath$=","+ipath$
      ypos$=""
      def_dir$=""
      hotkey$=""
      minimize$=""
    ELSE IF ypos%<=0
      iname$=","+iname$
      ipath$=","+ipath$
      xpos$=","+STR$(xpos%)
      def_dir$=""
      hoykey$=""
      minimize$=""
    ELSE IF def_dir$=""
      iname$=","+iname$
      ipath$=","+ipath$
      xpos$=","+STR$(xpos%)
      ypos$=","+STR$(ypos%)
      hoykey$=""
      minimize$=""
    ELSE IF hotkey$=""
      iname$=","+iname$
      ipath$=","+ipath$
      xpos$=","+STR$(xpos%)
      ypos$=","+STR$(ypos%)
      def_dir$=","+def_dir$
      minimize$=""
    ELSE IF MINimize$=""
      iname$=","+iname$
      ipath$=","+ipath$
      xpos$=","+STR$(xpos%)
      ypos$=","+STR$(ypos%)
      def_dir$=","+def_dir$
      hotkey$=","+hotkey$
    ELSE
      iname$=","+iname$
      ipath$=","+ipath$
      xpos$=","+STR$(xpos%)
      ypos$=","+STR$(ypos%)
      def_dir$=","+def_dir$
      hotkey$=","+hotkey$
      minimize$=","+MINimize$
    ENDIF
    item$="[AddItem("+cmd_line$+iname$+ipath$+iindex$+xpos$+ypos$+def_dir$+hotkey$+MINimize$+")]"+CHR$(0)
    POKE$ item%,item$
    ~PostMessage(serverw&,WM_DDE_EXECUTE,w&,MAKELONG(itemalloc&,0))
    wait_ack()
  ENDIF
  ~GlobalUnlock(itemalloc&)
  ~GlobalFree(itemalloc&)
RETURN
> PROCEDURE exit_progman(gname$)
  itemalloc& = GlobalAlloc(GMEM_DDESHARE,100)
  item% = GlobalLock(itemalloc&)
  IF gname$ = ""
    ALERT 1,"ExitProgman ERROR|Bad GroupName",1,"oops!!",alert|
  ELSE
    group$ = "[ExitProgman("+gname$+")]"+CHR$(0)
    ~PostMessage(serverw&,WM_DDE_EXECUTE,w&,MAKELONG(itemalloc&,0))
    wait_ack()
  ENDIF
  ~GlobalUnlock(itemalloc&)
  ~GlobalFree(itemalloc&)
  WIN #1
  PUT 0,0,grad&
RETURN
> PROCEDURE kill_dde
  ~PostMessage(serverw&,WM_DDE_UNADVISE,w&,0)
  ~PostMessage(serverw&,WM_DDE_TERMINATE,w&,0)
  wait_ack()
  @kill_cons()
RETURN
> PROCEDURE End_Main
  DISABLEW 1                    /* Kein Input Fenster#1
  IF LEN(exit_string$) < 2        /* Wenn Stringlänge...
    exit_string$ = "Please Take A Few Minutes to Read The Manual and send in the Registration Card."
  ENDIF
  t1$ = "Hotel Perfect was sucessfully installed. Install will now Open an Application Window in the Program Manager."
  DIALOG #0,(_X-348)/2,260,348,200,"",$90400002
    /* Dialogstruktur und Controls erstellen
    CONTROL t1$,100,"static",$10000001,30,10,270,90
    CONTROL exit_string$,101,"static",$10000001,20,95,290,80
    CONTROL "E&xit",102,"button",$10000000,110,155,100,30
  ENDDIALOG
  ~SetFocus(DLGITEM(0,102))     /* Focus setzen ID#102
  SHOWDIALOG #1                 /* Dialog zeigen
  REPEAT                        /* Schleife
    PEEKEVENT                   /* Nachricht?
  UNTIL MENU(0) = 102             /* raus wenn ID#102 gedückt
  CLOSEDIALOG #0                /* Dialog zu
RETURN
> PROCEDURE Read_Ini
  OPEN "i",#1,currentdir$ + "setup.ini"   /* INI-Datei öffnen
  INPUT #1,defaultdir$                  /* String/Felder/Var einlesen
  INPUT #1,dnum&
  IF dnum& > 0
    DIM dname$(dnum&)
    FOR i& = 1 TO dnum&
      INPUT #1,dname$(i&)
    NEXT i&
  ENDIF
  INPUT #1,itemnum&
  DIM itemdir$(itemnum&),iteminstall$(itemnum&),itemname$(itemnum&),type$(itemnum&),copydir$(itemnum&)
  FOR i& = 1 TO itemnum&
    INPUT #1,iteminstall$(i&)
    INPUT #1,itemname$(i&)
    INPUT #1,type$(i&)
    INPUT #1,itemdir$(i&)
    INPUT #1,copydir$(i&)
    IF copydir$(i&) = "DEFAULT" THEN copydir$(i&) = ""
    IF copydir$(i&) <> "" THEN copydir$(i&) = copydir$(i&)+"\"
  NEXT i&
  INPUT #1,groupname$
  INPUT #1,dspace$
  INPUT #1,winversion$
  INPUT #1,disk&
  INPUT #1,exit_string$
  INPUT #1,auto$
  INPUT #1,conf$
  INPUT #1,wini$
  INPUT #1,oth$
  CLOSE #1
  dspace$=STR$(VAL(dspace$)-150000)
RETURN
> PROCEDURE Check_Disk_Space
  installdrive = ASC(LEFT$(installdirto$,1)) - 64 /* Laufwerk feststellen
  IF DFREE(installdrive) < VAL(dspace$) /* wenn freier Speicherplatz....
    ALERT 1,"Insuffisent Disk Space to copy|you need at least "+dspace$+" bytes free",1,"Close",a&
    /* Fehlermeldung
    CLOSEW #1   /* Fenster zu
    END
  ENDIF
RETURN
> PROCEDURE Read_Info
  IF EXIST(currentdir$ + "info.fil")/* wenn .fil Datei existiert
    DO                                  /* Schleife
      PEEKEVENT                         /* Nachricht?
      OPEN "i",#1,currentdir$ + "info.fil"/* Datei öffnen
      INPUT #1,disk&                    /* Wert auslesen
      disk& = VAL(LEFT$(STR$(disk&),1))
      CLOSE #1                          /* Datei zu
      IF disk& <> currentdisk&          /* wenn...
        /*MESSAGE "Insert disk "+STR$(currentdisk&)+" in Disk Drive","Disk Change",MB_RETRYCANCEL|MB_TASKMODAL,n&
        ALERT 3,"Please Insert disk "+STR$(currentdisk&)+"|in Disk Drive "+UPPER$(LEFT$(currentdir$,2)),1," OK |Cancel",n&
        /* Meldung raus
      ENDIF
    LOOP UNTIL disk& = currentdisk& || n& = IDCANCEL/* raus hier wenn..
    IF message$ <> "" THEN        /* wenn String nicht leer
      ENABLEW DLG(5)            /* Input DLG(5) ermöglichen
      ~SetFocus(DLG(5))         /* setze Focus
    ENDIF
    IF n& = IDCANCEL            /* wenn Cancel
      CLOSEW #2                 /* Fenster#2 zu
      CLOSEW #1                 /* Fenster#1 zu
      END
    ENDIF
  ELSE
    DO                          /* Schleife
      MESSAGE "INFO.FIL Was Not Found! Cannot Continue.","File Not Found !",MB_RETRYCANCEL|MB_SYSTEMMODAL,n&
      /* Fehlermeldung
    LOOP UNTIL n& = IDCANCEL    /* raus hier wenn 'Cancel' gedrückt
    CLOSEW #1                   /* Fenster#1 zu
    END
  ENDIF
RETURN
> PROCEDURE Read_INF
  IF EXIST(currentdir$ + "file.inf")      /* wenn .inf Datei existiert
    OPEN "i",#1,currentdir$ + "file.inf"  /* Datei öffnen
    filecount&=1
    DO                                  /* Schleife
      INPUT #1,filename$(filecount&)    /* Felder einlesen
      INPUT #1,filesize%(filecount&)
      INPUT #1,filedir$(filecount&)
      IF filedir$(filecount&) = "DEFAULT" THEN filedir$(filecount&) = ""
      IF filedir$(filecount&) <> "" THEN filedir$(filecount&) = filedir$(filecount&)+"\"
      filecount& ++                      /* Zähler inkrementieren
      EXIT IF filecount& > 299          /* raus wenn größer 299
    LOOP UNTIL EOF(#1)                  /* raus wenn Dateiende
    CLOSE #1                            /* Datei zu
  ELSE                                  /* wenn Datei nicht existiert
    DO                          /* Schleife
      MESSAGE "FILE.INF Was Not Found! Cannot Continue.","File not Found",MB_RETRYCANCEL|MB_SYSTEMMODAL,n&
      /* Fehlermeldung
    LOOP UNTIL n& = IDCANCEL    /* raus wenn 'Cancel' gedrückt
    CLOSEW #1                   /* Fenster#1 zu
  ENDIF
RETURN
> PROCEDURE Change_Autoexec
  MESSAGE "Installer Must Make Changes To Your AUTOEXEC.BAT File.","AUTOEXEC.BAT CHANGE",MB_YESNOCANCEL|MB_TASKMODAL,n&
  /* Meldung anzeigen
  IF n& = IDCANCEL      /* wenn 'Cancel' gedrückt
    CLOSEW #1           /* Fenster zu
    END                 /* Programmende
  ENDIF
  IF n& = IDYES         /* wenn 'Ja' gedrückt
    install_drive$ = LEFT$(installdirto$,1)
    OPEN "a",#2,install_drive$ + ":\autoexec.bat"
    /* Datei#2 öffnen (Append Modus)
    OPEN "i",#1,currentdir$ + "setup.ini" /* Datei#1 öffnen zum Lesen
    autoexec$ = ""
    DO                          /* Schleife
      LINE INPUT #1,junk$       /* DummyString einlesen
    LOOP UNTIL junk$ = "[AUTOEXEC]"/* bis [AUTOEXEC] eingelesen
    DO                          /* Schleife
      LINE INPUT #1,junk$       /* DummyString einlesen
      EXIT IF junk$ = "[CONFIG]"/* bis [CONFIG] eingelesen
      PRINT #2,junk$            /* und an Datei#2 anhängen (Append)
    LOOP
    CLOSE #1    /* Datei#1 zu
    CLOSE #2    /* Datei#2 zu
  ENDIF
RETURN
> PROCEDURE Change_Config
  /* Beschreibung wie Procedure 'Change_Autoexec'
  MESSAGE "Installer must make changes to your Config.sys file.","Config.sys Change",MB_YESNOCANCEL|MB_TASKMODAL,n&
  IF n& = IDCANCEL
    CLOSEW #1
    END
  ENDIF
  IF n& = IDYES
    install_drive$ = LEFT$(installdirto$,1)
    OPEN "a",#2,install_drive$ + ":\config.sys"
    OPEN "i",#1,currentdir$+"setup.ini"
    config$ = ""
    DO
      LINE INPUT #1,junk$
    LOOP UNTIL junk$ = "[CONFIG]"
    DO
      LINE INPUT #1,junk$
      EXIT IF junk$ = "[WIN INI]"
      PRINT #2,junk$
    LOOP
    CLOSE #1
    CLOSE #2
  ENDIF
RETURN
> PROCEDURE Change_Win
  /* Beschreibung wie Procedure 'Change_Autoexec'
  MESSAGE "Installer must make changes to your Win.ini file.","Win.ini Change",MB_YESNOCANCEL|MB_TASKMODAL,n&
  IF n& = IDCANCEL
    CLOSEW #1
    END
  ENDIF
  IF n& = IDYES
    OPEN "a",#2,windir$+"\win.ini"
    OPEN "i",#1,currentdir$+"setup.ini"
    win_ini$ = ""
    DO
      LINE INPUT #1,junk$
    LOOP UNTIL junk$ = "[WIN INI]"
    PRINT #2,""
    DO
      LINE INPUT #1,junk$
      EXIT IF junk$ = "[OTHER]"
      PRINT #2,junk$
    LOOP
    CLOSE #1
    CLOSE #2
  ENDIF
RETURN
> PROCEDURE Change_Other
  /* Beschreibung wie Procedure 'Change_Autoexec'
  OPEN "i",#1,currentdir$+"setup.ini"
  change_other$ = ""
  change_other_name$ = ""
  DO
    LINE INPUT #1,junk$
  LOOP UNTIL junk$ = "[OTHER]"
  INPUT #1,change_other_name$
  MESSAGE "Installer must make changes to your "+change_other_name$+" file.",change_other_name$+" Change",MB_YESNOCANCEL|MB_TASKMODAL,n&
  IF n& = IDCANCEL
    CLOSEW #1
    END
  ENDIF
  IF n& = IDYES
    /*  IF EXIST(installdirto$+"\"+change_other_name$)
    /*  OPEN "a",#2,installdirto$+"\"+change_other_name$
    /*  ELSE
    OPEN "o",#2,installdirto$+"\"+change_other_name$
    /*  ENDIF
    DO
      LINE INPUT #1,junk$
      PRINT #2,junk$
    LOOP UNTIL EOF(#1)
    CLOSE #2
  ENDIF
  CLOSE #1
RETURN
