home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1990 / 12 / ldm / resiinst.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1990-10-29  |  37.8 KB  |  1,364 lines

  1. { -------------------------------------------------------- }
  2. {                       ResiInst V1.0                      }
  3. {    Menügesteuertes Installationsprogramm für Resident    }
  4. {           Copyright (C) 1990 by Torsten Priebe           }
  5. { -------------------------------------------------------- }
  6.  
  7. Program ResiInst;
  8.  
  9. Uses Dos, Crt;
  10.  
  11. Const
  12.   MpxNum   = $C0;         { Nummer für Multiplex-Interrupt }
  13.   MaxEntry = 5;             { Maximale Anzahl an Einträgem }
  14.  
  15.   ResPrev = 1;                 { Codes für Edit-Funktionen }
  16.   ResNext = 2;
  17.  
  18.   ColNorm    = 1;    { Farb-Codes für Bildschirmverwaltung }
  19.   ColHigh    = 2;
  20.   ColInverse = 3;
  21.   ColMarked  = 4;
  22.   ColError   = 5;
  23.  
  24.   WinTitle   = 1;            { Codes für Fensterverwaltung }
  25.   WinMain    = 2;
  26.   WinEdit    = 3;
  27.   WinMessage = 4;
  28.  
  29. Type
  30.   String4  = String[4];
  31.   String12 = String[12];
  32.   String13 = String[13];
  33.  
  34.   HotkeyObj = Object             { Objekt für einen Hotkey }
  35.                 Value : Word;                       { Wert }
  36.                              { liefert den Namen der Taste }
  37.                 Function Name: String12;
  38.  
  39.                 Function Edit: Byte;       { Edit-Funktion }
  40.               End;
  41.  
  42.   TitleObj = Object               { Objekt für einen Titel }
  43.                Value : String[32];                  { Wert }
  44.  
  45.                Function Edit: Byte;        { Edit-Funktion }
  46.              End;
  47.  
  48.   PathObj = Object       { Objekt für ein Startverzeichnis }
  49.               Value : String[64];                   { Wert }
  50.  
  51.               Function Edit: Byte;         { Edit-Funktion }
  52.             End;
  53.  
  54.   ProgObj = Object         { Objekt für eine Programmdatei }
  55.               Value : String[64];                   { Wert }
  56.  
  57.               Function Edit: Byte;         { Edit-Funktion }
  58.             End;
  59.  
  60.   EntryObj = Object  { Objekt für einen kompletten Eintrag }
  61.                Number   : Byte;      { Nummer des Eintrags }
  62.  
  63.                Hotkey   : HotkeyObj;              { Hotkey }
  64.                Title    : TitleObj;        { Programmtitel }
  65.                Path     : PathObj;      { Startverzeichnis }
  66.                ProgName : ProgObj;         { Programmdatei }
  67.  
  68.                Procedure Show;          { Eintrag anzeigen }
  69.                Procedure Edit;         { Eintrag editieren }
  70.              End;
  71.  
  72.   InputObj = Object       { Objekt für eine Eingaberoutine }
  73.                Value     : String;                  { Wert }
  74.                MaxLen,            { Max. Länge der Eingabe }
  75.                X, Y,                         { Koordinaten }
  76.                I         : Byte;     { akt. Cursorposition }
  77.  
  78.                Constructor Init;          { Initialisieren }
  79.                                    { testen ob Wert gültig }
  80.                Function CheckValue: Boolean; Virtual;
  81.                            { einen Tastendruck verarbeiten }
  82.                Function ManageKey(Ch: Char): Byte; Virtual;
  83.                                { eigentliche Edit-Funktion }
  84.                Function Edit: Byte;
  85.              End;
  86.  
  87.   ChooseObj = Object             { Objekt zur Dateiauswahl }
  88.                 CPath         : DirStr; { akt. Verzeichnis }
  89.                                      { wählbare Dateinamen }
  90.                 Data          : Array[1..255] Of String13;
  91.                 Count, Count_,     { Anzahl der Dateinamen }
  92.                 Bar, Scroll   : Byte;     { Balkenposition }
  93.  
  94.                 Constructor Init;         { Initialisieren }
  95.                 Procedure ShowData;  { Dateinamen anzeigen }
  96.                                           { Daten einlesen }
  97.                 Procedure ReadData; Virtual;
  98.                                    { Wahlfenster schließen }
  99.                 Procedure Close; Virtual;
  100.                                { eigentliche Wahl-Funktion }
  101.                 Function Choose(Var Path: PathStr): String12;
  102.               End;
  103.  
  104.   DataType = Array[1..MaxEntry] Of EntryObj;       { Daten }
  105.  
  106.                     { Resident-Daten (im Assembler-Format) }
  107.   ResiDataType = Array[1..MaxEntry] Of Record
  108.                    Hotkey   : Word;
  109.                    Title    : Array[1..32] Of Char;
  110.                    Path,
  111.                    ProgName : Array[1..64] Of Char;
  112.                  End;
  113.  
  114. Var
  115.   Data        : DataType;                          { Daten }
  116.   EntryCount  : Byte;                { Anzahl der Einträge }
  117.   ResiDataPtr : ^ResiDataType;            { Resident-Daten }
  118.  
  119.   InitMode    : Integer;    { Videomodus bei Programmstart }
  120.   ExitSav     : Pointer;               { Alte Exit-Routine }
  121.  
  122.   CurrWind    : Byte;           { momentan aktives Fenster }
  123.  
  124. { -- Hilfsroutinen --------------------------------------- }
  125.  
  126. Procedure HideCursor;                 { Cursor ausschalten }
  127. Var
  128.   Regs : Registers;
  129. Begin
  130.   Regs.AH:=$01;
  131.   Regs.CX:=$2000;
  132.   Intr($10, Regs);
  133. End;
  134.  
  135. Procedure ShowCursor;                 { Cursor einschalten }
  136. Var
  137.   Regs : Registers;
  138. Begin
  139.   Regs.AH:=$01;
  140.   If LastMode=Mono Then Regs.CX:=$0C0D Else Regs.CX:=$0607;
  141.   Intr($10, Regs);
  142. End;
  143.  
  144.        { String vom Assembler- ins Pascal-Format umwandeln }
  145. Function ConvString(S: String): String;
  146. Var
  147.   I: Byte;
  148. Begin
  149.   I:=1;
  150.   While S[I]<>#0 Do Inc(I);
  151.   S:=Copy(S, 1, I-1);
  152.   ConvString:=S;
  153. End;
  154.  
  155.     { Leerzeichen an Anfang und Ende eines Strings löschen }
  156. Function CutString(S: String): String;
  157. Begin
  158.   While (S<>'') And (S[1]=' ') Do Delete(S, 1, 1);
  159.   While (S<>'') And (S[Length(S)]=' ') Do
  160.     Delete(S, Length(S), 1);
  161.   CutString:=S;
  162. End;
  163.  
  164. { -- Bildschirmverwaltung -------------------------------- }
  165.  
  166. Procedure SetColor(Color: Byte);            { Farbe sezten }
  167. Begin
  168.   If LastMode In [Mono, BW80] Then Case Color Of
  169.     ColNorm    : TextAttr:=LightGray;
  170.     ColHigh    : TextAttr:=White;
  171.     ColInverse : TextAttr:=White;
  172.     ColMarked  : TextAttr:=LightGray Shl 4;
  173.     ColError   : TextAttr:=LightGray Shl 4;
  174.   End Else Case Color Of
  175.     ColNorm    : TextAttr:=Green;
  176.     ColHigh    : TextAttr:=LightGray;
  177.     ColInverse : TextAttr:=Cyan Shl 4;
  178.     ColMarked  : TextAttr:=Blue Shl 4 + LightGray;
  179.     ColError   : TextAttr:=Red Shl 4 + White;
  180.   End;
  181. End;
  182.  
  183. Procedure SetWindow(Wind: Byte);      { Fenster aktivieren }
  184. Begin
  185.   Case Wind Of
  186.     WinTitle   : Window(2, 2, 79, 3);
  187.     WinMain    : Window(2, 5, 79, 16);
  188.     WinEdit    : Window(2, 18, 79, 21);
  189.     WinMessage : Window(2, 23, 79, 24);
  190.   End;
  191.   CurrWind:=Wind;
  192. End;
  193.  
  194. Procedure InitScreen;          { Bildschirm initialisieren }
  195. Var
  196.   I : Byte;
  197. Begin
  198.   InitMode:=LastMode;     { Videomodus prüfen / neu setzen }
  199.   Case LastMode Of
  200.     BW80, CO80, Mono   : ;
  201.     BW40, BW40+Font8x8,
  202.     BW80+Font8x8       : TextMode(BW80);
  203.     Else                 TextMode(CO80);
  204.   End;
  205.  
  206.   SetColor(ColNorm); ClrScr;          { Bildschirm löschen }
  207.  
  208.   HideCursor;
  209.   WindMax:=$FFFF;                  { Scrolling ausschalten }
  210.  
  211.   GotoXY(1, 1);                          { Rahmen aufbauen }
  212.   Write('╔'); For I:=1 To 78 Do Write('═'); Write('╗');
  213.   For I:=2 To 3 Do Begin
  214.     GotoXY(1, I); Write('║');
  215.     GotoXY(80, I); Write('║');
  216.   End;
  217.   GotoXY(1, 4);
  218.   Write('╠'); For I:=1 To 78 Do Write('═'); Write('╣');
  219.   For I:=5 To 16 Do Begin
  220.     GotoXY(1, I); Write('║');
  221.     GotoXY(80, I); Write('║');
  222.   End;
  223.   GotoXY(1, 17);
  224.   Write('╠'); For I:=1 To 78 Do Write('═'); Write('╣');
  225.   For I:=18 To 21 Do Begin
  226.     GotoXY(1, I); Write('║');
  227.     GotoXY(80, I); Write('║');
  228.   End;
  229.   GotoXY(1, 22);
  230.   Write('╠'); For I:=1 To 78 Do Write('═'); Write('╣');
  231.   For I:=23 To 24 Do Begin
  232.     GotoXY(1, I); Write('║');
  233.     GotoXY(80, I); Write('║');
  234.   End;
  235.   GotoXY(1, 25);
  236.   Write('╚'); For I:=1 To 78 Do Write('═'); Write('╝');
  237.  
  238.   Window(1, 1, 80, 25);             { Fenster zurücksetzen }
  239.  
  240.   SetWindow(WinTitle);        { Titel / Copyright ausgeben }
  241.   SetColor(ColInverse); ClrScr;
  242.   GotoXY(34, 1);
  243.   Write('ResiInst V1.0');
  244.   GotoXY(22, 2);
  245.   Write('Copyright (C) 1990 by Torsten Priebe');
  246.  
  247.   SetWindow(WinMain);   { Gerüst für Dateneingabe aufbauen }
  248.   SetColor(ColNorm);
  249.   GotoXY(62, 3); Write('Eintrag   von  ');
  250.   GotoXY(13, 5); Write('Hotkey: ');
  251.   GotoXY(6, 6); Write('Programmtitel: ');
  252.   GotoXY(3, 8); Write('Startverzeichnis: ');
  253.   GotoXY(6, 9); Write('Programmdatei: ');
  254.  
  255.   SetWindow(WinMessage);        { Meldungsfenster aufbauen }
  256.   SetColor(ColInverse); ClrScr;
  257. End;
  258.  
  259. {$F+}
  260. Procedure CloseScreen;           { Bildschirm zurücksetzen }
  261. Begin
  262.                             { ggf. Videomodus zurücksetzen }
  263.   If LastMode<>InitMode Then TextMode(InitMode);
  264.  
  265.   TextAttr:=LightGray;                { Bildschirm löschen }
  266.   Window(1, 1, 80, 25);
  267.   ClrScr;
  268.   ShowCursor;
  269.   ExitProc:=ExitSav;
  270. End;
  271. {$F-}
  272.  
  273. { -- Fehlermeldung, Statuszeile -------------------------- }
  274.  
  275. Procedure Error(Message: String);          { Fehlermeldung }
  276. Var
  277.   WindSav : Byte;
  278. Begin
  279.   WindSav:=CurrWind;                { akt. Fensten sichern }
  280.  
  281.   SetWindow(WinMessage);          { Fehlermeldung ausgeben }
  282.   GotoXY(1, 2);
  283.   SetColor(ColError); ClrEol;
  284.   Message:=Message+' Weiter mit <Esc>';
  285.   GotoXY((78-Length(Message)) Div 2, 2);
  286.   Write(Message, ^G);
  287.  
  288.   Repeat Until Readkey=#27;
  289.  
  290.   GotoXY(1, 2);                    { Fehlermeldung löschen }
  291.   SetColor(ColInverse); ClrEol;
  292.   SetWindow(WindSav);
  293. End;
  294.  
  295. Procedure Status(Status: String);            { Statuszeile }
  296. Var
  297.   WindSav : Byte;
  298. Begin
  299.   WindSav:=CurrWind;                { akt. Fenster sichern }
  300.  
  301.   SetWindow(WinMessage);                 { Status ausgeben }
  302.   SetColor(ColInverse);
  303.   GotoXY(1, 1); ClrEol;
  304.   GotoXY((78-Length(Status)) Div 2, 1);
  305.   Write(Status);
  306.   SetWindow(WindSav);
  307. End;
  308.  
  309. { -- Objekt: InputObj ------------------------------------ }
  310.  
  311. Constructor InputObj.Init;                { Initialisieren }
  312. Begin
  313.                           { Wert mit Leerzeichen auffüllen }
  314.   While Length(Value)<MaxLen Do Value:=Value+' ';
  315.   I:=1;
  316. End;
  317.  
  318. Function InputObj.CheckValue: Boolean;       { Wert prüfen }
  319. Begin
  320.   CheckValue:=True;  { Oberste Instanz hat keine Bedingung }
  321. End;
  322.  
  323.                                    { Tastendruck auswerten }
  324. Function InputObj.ManageKey(Ch: Char): Byte;
  325. Var
  326.   Res : Byte;
  327. Begin
  328.   Res:=0;
  329.   Case Ch Of
  330.     #0: Case Readkey Of
  331.                                              { Pfeiltasten }
  332.           'H': If CheckValue Then Res:=ResPrev Else I:=1;
  333.           'P': If CheckValue Then Res:=ResNext Else I:=1;
  334.           'K': If I>1 Then Dec(I);
  335.           'M': If I<MaxLen Then Inc(I);
  336.  
  337.           'S': Begin                              { Delete }
  338.                  Delete(Value, I, 1); Value:=Value+' ';
  339.                End;
  340.         End;
  341.     #8: If I>1 Then Begin                      { Backspace }
  342.           Delete(Value, I-1, 1); Value:=Value+' ';
  343.           Dec(I);
  344.         End;
  345.     #13: If CheckValue Then                       { Return }
  346.            Res:=ResNext Else I:=1;
  347.     #27: Begin                                    { Escape }
  348.            Value:='';
  349.            While Length(Value)<MaxLen Do Value:=Value+' ';
  350.            I:=1;
  351.          End;
  352.     #32..#126,                       { Eingabe von Zeichen }
  353.     #128..#255: Begin
  354.                   Value[I]:=Ch;
  355.                   If I<MaxLen Then Inc(I);
  356.                 End;
  357.   End;
  358.   ManageKey:=Res;
  359. End;
  360.  
  361. Function InputObj.Edit: Byte;  { eigentliche Edit-Funktion }
  362. Var
  363.   Ch  : Char;
  364.   Res : Byte;
  365. Begin
  366.   Repeat
  367.     GotoXY(X, Y);                 { Eingabebalken ausgeben }
  368.     SetColor(ColMarked);
  369.     Write(Value);
  370.     GotoXY(X+I-1, Y);
  371.  
  372.     ShowCursor;                   { auf Tastendruck warten }
  373.     Ch:=Readkey;
  374.     HideCursor;
  375.  
  376.     Res:=ManageKey(Ch);          { Tastendruck verarbeiten }
  377.   Until Res<>0;
  378.                       { Eingabe von Leerzeichen bereinigen }
  379.   Value:=CutString(Value);
  380.   Edit:=Res;
  381. End;
  382.  
  383. { -- Objekt: ChooseObj ----------------------------------- }
  384.  
  385. Constructor ChooseObj.Init;               { Initialisieren }
  386. Begin
  387.   SetWindow(WinEdit);
  388.   Count:=0; Count_:=0;
  389. End;
  390.  
  391. Procedure ChooseObj.ShowData;             { Daten anzeigen }
  392. Var
  393.   I : Byte;
  394. Begin
  395.   For I:=Scroll To Scroll+19 Do Begin
  396.     If I=Bar Then SetColor(ColMarked) Else
  397.       SetColor(ColHigh);
  398.     GotoXY((((I-Scroll) Mod 5)*15)+2, (I-Scroll) Div 5+1);
  399.     If I>Count Then Write('':15) Else
  400.       Write(' ', Data[I], '':13-Length(Data[I]), ' ');
  401.   End;
  402. End;
  403.  
  404. Procedure ChooseObj.ReadData;             { Daten einlesen }
  405. Begin
  406.   Count:=0;    { oberste Instanz kann keine Daten einlesen }
  407.   Count_:=0;
  408. End;
  409.  
  410. Procedure ChooseObj.Close;         { Wahlfenster schließen }
  411. Var
  412.   I : Byte;
  413. Begin
  414.   SetColor(ColNorm);                     { Fenster löschen }
  415.   ClrScr;
  416.  
  417.   Window(1, 1, 80, 25);         { Verzeichnisnamen löschen }
  418.   GotoXY(2, 17);
  419.   For I:=1 To 78 Do Write('═');
  420.   SetWindow(WinEdit);
  421. End;
  422.  
  423.                             { eigentliche Auswahl-Funktion }
  424. Function ChooseObj.Choose(Var Path: PathStr): String12;
  425. Var
  426.   Ch : Char;
  427.   I  : Byte;
  428.   P  : PathStr;
  429. Begin
  430.   Repeat
  431.     If Count=0 Then Begin   { noch keine Daten eingelesen? }
  432.       Window(1, 1, 80, 25);     { Verzeichnisnamen löschen }
  433.       SetColor(ColNorm);
  434.       GotoXY(2, 17);
  435.       For I:=1 To 78 Do Write('═');
  436.       P:=CPath;                { Verzeichnisnamen anzeigen }
  437.       If Length(P)>3 Then Delete(P, Length(P), 1);
  438.       P:=' '+P+' ';
  439.       SetColor(ColInverse);
  440.       GotoXY(40-Length(P) Div 2, 17);
  441.       Write(P);
  442.       SetWindow(WinEdit);
  443.  
  444.       ReadData;                           { Daten einlesen }
  445.  
  446.       If Count=0 Then Begin      { keine Einträge gefunden }
  447.         SetColor(ColNorm); ClrScr;
  448.         Error('Keine Einträge gefunden!');
  449.         Close;
  450.         Choose:='';
  451.         Exit;
  452.       End;
  453.  
  454.       Bar:=1; Scroll:=1;
  455.     End;
  456.  
  457.     ShowData;                             { Daten anzeigen }
  458.     Ch:=Readkey;
  459.     Case Ch Of                     { Tastendruck auswerten }
  460.       #0: Case Readkey Of
  461.             'K': If Bar>1 Then Begin         { Pfeiltasten }
  462.                    Dec(Bar);
  463.                    If Bar<Scroll Then Dec(Scroll, 5);
  464.                  End;
  465.             'H': If Bar>5 Then Begin
  466.                    Dec(Bar, 5);
  467.                    If Bar<Scroll Then Dec(Scroll, 5);
  468.                  End;
  469.             'M': If Bar<Count Then Begin
  470.                    Inc(Bar);
  471.                    If Bar>Scroll+19 Then Inc(Scroll, 5);
  472.                  End;
  473.             'P': If Bar<Count-4 Then Begin
  474.                    Inc(Bar, 5);
  475.                    If Bar>Scroll+19 Then Inc(Scroll, 5);
  476.                  End;
  477.           End;
  478.       #13: Begin                                  { Return }
  479.              If Bar>Count_ Then Begin        { Verzeichnis }
  480.                CPath:=FExpand(CPath+Data[Bar]);
  481.                Count:=0;
  482.              End Else Begin                        { Datei }
  483.                Path:=CPath;
  484.                Choose:=Data[Bar];
  485.                Close;
  486.                Exit;
  487.              End;
  488.            End;
  489.     End;
  490.   Until Ch=#27;
  491.   Choose:='';
  492.   Close;
  493. End;
  494.  
  495. { -- Objekt: HotkeyObj ----------------------------------- }
  496.  
  497. {$I HOTKEYS.INC}
  498.  
  499. Function HotkeyObj.Name: String12;        { Name der Taste }
  500. Var
  501.   I : Byte;
  502.   S : String;
  503. Begin
  504.   S:='';
  505.   For I:=1 To Hotkeys Do             { Tabelle durchsuchen }
  506.     If HotKeyList[I].Code=Value Then Begin
  507.       S:='<'+HotKeyList[I].Name+'>';
  508.       I:=Hotkeys;
  509.     End;
  510.   Name:=S;
  511. End;
  512.  
  513. Function HotkeyObj.Edit: Byte;      { Hotkey-Edit-Funktion }
  514.  
  515. Function CheckHotkey: Boolean;            { Hotkey gültig? }
  516. Begin
  517.   If Name='' Then Begin
  518.     CheckHotkey:=False; Error('Ungültiger Hotkey!');
  519.   End Else CheckHotkey:=True;
  520. End;
  521.  
  522. Var
  523.   Regs : Registers;
  524.   Res  : Byte;
  525.   W    : Word;
  526.  
  527. Begin
  528.   Status('Bitte betätigen Sie den gewünschten Hotkey!');
  529.  
  530.   Res:=0;
  531.   Repeat
  532.     GotoXY(22, 5);         { Hotkey-Feld markiert ausgeben }
  533.     SetColor(ColMarked);
  534.     Write(Name, '':12-Length(Name));
  535.  
  536.     Regs.AH:=$00;     { auf Tastendruck via Int 16h warten }
  537.     Intr($16, Regs);
  538.  
  539.     If Regs.AX=$4800 Then Begin               { Pfeil rauf }
  540.       If CheckHotkey Then Res:=ResPrev;
  541.     End Else If Regs.AX=$5000 Then Begin    { Pfeil runter }
  542.       If CheckHotkey Then Res:=ResNext;
  543.     End Else If Regs.AX=$011B Then Begin          { Escape }
  544.       Value:=0;
  545.     End Else Begin
  546.       W:=Value;
  547.       Value:=Regs.AX;                { Hotkey ausprobieren }
  548.       If CheckHotkey Then Res:=ResNext Else Value:=W;
  549.     End;
  550.   Until (Res<>0);
  551.   Edit:=Res;
  552. End;
  553.  
  554. { -- Objekt: TitleObj ------------------------------------ }
  555.  
  556. Type
  557.   TitleInputObj = Object (InputObj)      { Eingabefunktion }
  558.                     Constructor Init;
  559.                     Function CheckValue: Boolean; Virtual;
  560.                   End;
  561.  
  562. Constructor TitleInputObj.Init;       { neue Init-Funktion }
  563. Begin
  564.   MaxLen:=32;
  565.   X:=22; Y:=6;
  566.   InputObj.Init;
  567. End;
  568.  
  569.                                  { neue Gültigkeitsprüfung }
  570. Function TitleInputObj.CheckValue: Boolean;
  571. Begin
  572.   If CutString(Value)='' Then Begin
  573.     CheckValue:=False; Error('Ungültiger Programmtitel!');
  574.   End Else CheckValue:=True;
  575. End;
  576.  
  577. Function TitleObj.Edit: Byte;        { Titel-Edit-Funktion }
  578. Var
  579.   TitleInput: TitleInputObj;
  580. Begin
  581.   Status('Bitte geben Sie den Programmtitel ein!');
  582.  
  583.   TitleInput.Value:=Value;
  584.   TitleInput.Init;
  585.   Edit:=TitleInput.Edit;
  586.   Value:=TitleInput.Value;
  587. End;
  588.  
  589. { -- Objekt: PathObj ------------------------------------- }
  590.  
  591. Type                              { angepaßte Wahlfunktion }
  592.   PathChooseObj = Object (ChooseObj)
  593.                     Constructor Init;
  594.                     Procedure ReadData; Virtual;
  595.                     Procedure Close; Virtual;
  596.                   End;
  597.  
  598.   PathInputObj = Object (InputObj)       { Eingabefunktion }
  599.                    Constructor Init;
  600.                    Function CheckValue: Boolean; Virtual;
  601.                    Function ManageKey(Ch: Char): Byte;
  602.                             Virtual;
  603.                  End;
  604.  
  605. Constructor PathChooseObj.Init;  { Auswahl-Initialisierung }
  606. Begin
  607.   Status('Bitte wählen Sie das Startverzeichnis und '+
  608.          'betätigen Sie <Return>!');
  609.   ChooseObj.Init;
  610. End;
  611.  
  612. Procedure PathChooseObj.ReadData;         { Daten einlesen }
  613. Var
  614.   F : SearchRec;
  615.   P : PathStr; D : DirStr; N : NameStr; E : ExtStr;
  616. Begin
  617.   Count:=0;
  618.  
  619.   Inc(Count);                { erster Wert ist Verzeichnis }
  620.   P:=CPath;
  621.   If Length(P)>3 Then Begin
  622.     Delete(P, Length(P), 1);
  623.     FSplit(P, D, N, E);
  624.     P:=N+E;
  625.   End;
  626.   Data[Count]:=P;
  627.   Count_:=Count;
  628.  
  629.                                { Unterverzeichnisse suchen }
  630.   FindFirst(CPath+'*.*', Directory, F);
  631.   While DosError=0 Do Begin
  632.     If (F.Attr And Directory<>0) And
  633.        (F.Name<>'.') Then Begin
  634.       Inc(Count);
  635.       Data[Count]:=F.Name+'\';
  636.     End;
  637.     FindNext(F);
  638.   End;
  639. End;
  640.  
  641. Procedure PathChooseObj.Close;  { Auswahlfenster schließen }
  642. Begin
  643.   ChooseObj.Close;
  644.   Status('Bitte geben Sie das Startverzeichnis ein! '+
  645.          'Wählen mit <Leertaste>');
  646. End;
  647.  
  648. Constructor PathInputObj.Init;    { Eingabe initialisieren }
  649. Begin
  650.   MaxLen:=48;
  651.   X:=22; Y:=8;
  652.   InputObj.Init;
  653. End;
  654.  
  655.                                  { neue Gültigkeitsprüfung }
  656. Function PathInputObj.CheckValue: Boolean;
  657. Var
  658.   F : SearchRec;
  659.   S : String[64];
  660. Begin
  661.   S:=CutString(Value);
  662.   If S='' Then DosError:=3 Else Begin
  663.     S:=FExpand(S);
  664.     If S[Length(S)]<>'\' Then S:=S+'\';
  665.     FindFirst(S+'*.*', AnyFile, F);
  666.   End;
  667.   If Not (DosError In [0, 18]) Then Begin
  668.     CheckValue:=False;
  669.     Error('Ungültiges Startverzeichnis!');
  670.   End Else CheckValue:=True;
  671. End;
  672.  
  673.                       { erweiterte Tastendruckverarbeitung }
  674. Function PathInputObj.ManageKey(Ch: Char): Byte;
  675. Var
  676.   Res        : Byte;
  677.   P          : PathStr;
  678.   F          : SearchRec;
  679.   PathChoose : PathChooseObj;
  680.   S          : String12;
  681. Begin
  682.   Res:=0;
  683.   If Ch=' ' Then Begin             { bei Leertaste Auswahl }
  684.     P:=FExpand(CutString(Value));
  685.     If P[Length(P)]<>'\' Then P:=P+'\';
  686.     FindFirst(P+'*.*', AnyFile, F);
  687.     If Not (DosError In [0, 18]) Then Begin
  688.       If Length(P)>3 Then Delete(P, Length(P), 1);
  689.       Error('Verzeichnis '+P+' existiert nicht!');
  690.       P:=FExpand('');
  691.     End;
  692.  
  693.     PathChoose.CPath:=P;
  694.     PathChoose.Init;
  695.     S:=PathChoose.Choose(P);
  696.     If Length(P)>3 Then Delete(P, Length(P), 1);
  697.     If S<>'' Then Begin
  698.       Value:=P;
  699.       While Length(Value)<MaxLen Do Value:=Value+' ';
  700.       Res:=ResNext;
  701.     End;
  702.     I:=1;
  703.     SetWindow(WinMain);
  704.   End Else Res:=InputObj.ManageKey(Ch);
  705.   ManageKey:=Res;
  706. End;
  707.  
  708. Function PathObj.Edit: Byte;       { Pfad-Eingabe-Funktion }
  709. Var
  710.   PathInput: PathInputObj;
  711. Begin
  712.   Status('Bitte geben Sie das Startverzeichnis ein! '+
  713.          'Wählen mit <Leertaste>');
  714.  
  715.   PathInput.Value:=Value;
  716.   PathInput.Init;
  717.   Edit:=PathInput.Edit;
  718.   Value:=FExpand(PathInput.Value);
  719. End;
  720.  
  721. { -- Objekt: ProgObj ------------------------------------- }
  722.  
  723. Type                           { angepaßte Auswahlfunktion }
  724.   ProgChooseObj = Object (ChooseObj)
  725.                     Constructor Init;
  726.                     Procedure ReadData; Virtual;
  727.                     Procedure Close; Virtual;
  728.                   End;
  729.  
  730.   ProgInputObj = Object (InputObj)       { Eingabefunktion }
  731.                    Constructor Init;
  732.                    Function CheckValue: Boolean; Virtual;
  733.                    Function ManageKey(Ch: Char): Byte;
  734.                             Virtual;
  735.                  End;
  736.  
  737. Constructor ProgChooseObj.Init;   { Auswahl initialisieren }
  738. Begin
  739.   Status('Bitte wählen Sie die Programmdatei und '+
  740.          'betätigen Sie <Return>!');
  741.   ChooseObj.Init;
  742. End;
  743.  
  744. Procedure ProgChooseObj.ReadData;         { Daten einlesen }
  745. Var
  746.   F : SearchRec;
  747.   P : PathStr; D : DirStr; N : NameStr; E : ExtStr;
  748. Begin
  749.   Count:=0;
  750.  
  751.                                   { Programmdateien suchen }
  752.   FindFirst(CPath+'*.*', ReadOnly Or Archive, F);
  753.   While DosError=0 Do Begin
  754.     P:=F.Name;
  755.     FSplit(P, D, N, E);
  756.     If (E='.COM') Or (E='.EXE') Then Begin
  757.       Inc(Count);
  758.       Data[Count]:=F.Name;
  759.     End;
  760.     FindNext(F);
  761.   End;
  762.   Count_:=Count;
  763.  
  764.                                     { Verzeichnisse suchen }
  765.   FindFirst(CPath+'*.*', Directory, F);
  766.   While DosError=0 Do Begin
  767.     If (F.Attr And Directory<>0) And
  768.        (F.Name<>'.') Then Begin
  769.       Inc(Count);
  770.       Data[Count]:=F.Name+'\';
  771.     End;
  772.     FindNext(F);
  773.   End;
  774. End;
  775.  
  776. Procedure ProgChooseObj.Close;  { Auswahlfenster schließen }
  777. Begin
  778.   ChooseObj.Close;
  779.   Status('Bitte geben Sie den Namen der Programmdatei '+
  780.          'ein! Wählen mit <Leertaste>');
  781. End;
  782.  
  783. Constructor ProgInputObj.Init;    { Eingabe initialisieren }
  784. Begin
  785.   MaxLen:=48;
  786.   X:=22; Y:=9;
  787.   InputObj.Init;
  788. End;
  789.  
  790.                                  { neue Gültigkeitsprüfung }
  791. Function ProgInputObj.CheckValue: Boolean;
  792. Var
  793.   F : SearchRec;
  794.   S : PathStr;
  795.   D : DirStr; N : NameStr; E : ExtStr;
  796. Begin
  797.   S:=CutString(Value);
  798.   If S='' Then DosError:=18 Else Begin
  799.     S:=FExpand(S);
  800.     FSplit(S, D, N, E);
  801.     If (E<>'.COM') And (E<>'.EXE') Then DosError:=18 Else
  802.       FindFirst(S, ReadOnly+SysFile+Archive, F);
  803.   End;
  804.  
  805.   If DosError<>0 Then Begin
  806.     CheckValue:=False; Error('Ungültige Programmdatei!');
  807.   End Else CheckValue:=True;
  808. End;
  809.  
  810.                       { erweiterte Tastendruckverarbeitung }
  811. Function ProgInputObj.ManageKey(Ch: Char): Byte;
  812. Var
  813.   Res        : Byte;
  814.   F          : SearchRec;
  815.   ProgChoose : ProgChooseObj;
  816.   S          : String12;
  817.   P : PathStr; D : DirStr; N : NameStr; E : ExtStr;
  818. Begin
  819.   Res:=0;
  820.   If Ch=' ' Then Begin             { Auswahl bei Leertaste }
  821.     P:=FExpand(CutString(Value));
  822.     If P[Length(P)]<>'\' Then Begin
  823.       FindFirst(P, Directory, F);
  824.       If (DosError<>0) Or
  825.          (F.Attr And Directory=0) Then Begin
  826.         FSplit(P, D, N, E);
  827.         P:=D;
  828.       End Else P:=P+'\';
  829.     End;
  830.  
  831.     FindFirst(P+'*.*', AnyFile, F);
  832.     If Not (DosError In [0, 18]) Then Begin
  833.       If Length(P)>3 Then Delete(P, Length(P), 1);
  834.       Error('Verzeichnis '+P+' existiert nicht!');
  835.       P:=FExpand('');
  836.     End;
  837.  
  838.     ProgChoose.CPath:=P;
  839.     ProgChoose.Init;
  840.     S:=ProgChoose.Choose(P);
  841.     If S<>'' Then Begin
  842.       Value:=P+S;
  843.       While Length(Value)<MaxLen Do Value:=Value+' ';
  844.       Res:=ResNext;
  845.     End;
  846.     I:=1;
  847.     SetWindow(WinMain);
  848.   End Else Res:=InputObj.ManageKey(Ch);
  849.   ManageKey:=Res;
  850. End;
  851.  
  852. Function ProgObj.Edit: Byte;       { Programm-Edit-Funkton }
  853. Var
  854.   ProgInput: ProgInputObj;
  855. Begin
  856.   Status('Bitte geben Sie den Namen der Programmdatei '+
  857.          'ein! Wählen mit <Leertaste>');
  858.  
  859.   ProgInput.Value:=Value;
  860.   ProgInput.Init;
  861.   Edit:=ProgInput.Edit;
  862.   Value:=FExpand(ProgInput.Value);
  863. End;
  864.  
  865. { -- Objekt: EntryObj ------------------------------------ }
  866.  
  867. Procedure EntryObj.Show;                { Eintrag anzeigen }
  868. Begin
  869.   SetWindow(WinMain);
  870.   SetColor(ColHigh);
  871.   GotoXY(70, 3);
  872.   Write(Number);
  873.   GotoXY(76, 3);
  874.   Write(EntryCount);
  875.   GotoXY(22, 5);
  876.   Write(Hotkey.Name, '':12-Length(Hotkey.Name));
  877.   GotoXY(22, 6);
  878.   Write(Title.Value, '':32-Length(Title.Value));
  879.   GotoXY(22, 8);
  880.   Write(Path.Value, '':48-Length(Path.Value));
  881.   GotoXY(22, 9);
  882.   Write(ProgName.Value, '':48-Length(ProgName.Value));
  883. End;
  884.  
  885. Procedure EntryObj.Edit;              { Eintrag bearbeiten }
  886.  
  887. Var
  888.   Bar, Res : Byte;
  889.   Ch       : Char;
  890.   EntryOk  : Boolean;      { Flag für "Eintrag akzeptiert" }
  891.  
  892.                  { Edit-Funktion für "Eintrag akzeptieren" }
  893. Function EntryOkEdit: Byte;
  894. Begin
  895.   Status('Betätigen Sie <Return> um den Eintrag zu '+
  896.          'akzeptieren!');
  897.  
  898.   SetColor(ColMarked);
  899.   GotoXY(22, 11); Write(' Eintrag akzeptieren ');
  900.   Repeat
  901.     Ch:=Readkey; If Ch=#13 Then EntryOk:=True;
  902.     If Ch=#0 Then Case Readkey Of
  903.       'H': Res:=ResPrev;
  904.       'P': Res:=ResNext;
  905.     End;
  906.   Until (Res<>0) Or EntryOk;
  907.   EntryOkEdit:=Res;
  908. End;
  909.  
  910. Begin
  911.   Bar:=1;
  912.   EntryOk:=False;
  913.  
  914.   Repeat
  915.     Show;     { Eintrag und "Eintrag akzeptieren" anzeigen }
  916.     SetColor(ColInverse);
  917.     GotoXY(22, 11); Write(' Eintrag akzeptieren ');
  918.  
  919.     Case Bar Of           { Entspr. Edit-Funktion aufrufen }
  920.       1: Res:=Hotkey.Edit;
  921.       2: Res:=Title.Edit;
  922.       3: Res:=Path.Edit;
  923.       4: Res:=ProgName.Edit;
  924.       5: Res:=EntryOkEdit;
  925.     End;
  926.  
  927.     Case Res Of              { Funktionsergebnis auswerten }
  928.       ResPrev: If Bar>1 Then Dec(Bar);
  929.       ResNext: If Bar<5 Then Inc(Bar);
  930.     End;
  931.   Until EntryOk;
  932.   Show;
  933.   SetColor(ColNorm);
  934.   GotoXY(22, 11); Write('                     ');
  935. End;
  936.  
  937. { -- Hauptteil ------------------------------------------- }
  938.  
  939. Procedure GetData;         { Daten von Resident übernehmen }
  940. Var
  941.   Regs  : Registers;
  942.   I     : Byte;
  943. Begin
  944.   FillChar(Data, SizeOf(Data), 0);
  945.   For I:=1 To MaxEntry Do Data[I].Number:=I;
  946.   Regs.AH:=MpxNum;
  947.   Regs.AL:=$00;
  948.   Intr($2F, Regs);
  949.  
  950.   If Regs.AL=$FF Then Begin        { Resident installiert? }
  951.     ResiDataPtr:=Ptr(Regs.ES, Regs.BX);
  952.     I:=1;
  953.     While (I<=MaxEntry) And (ResiDataPtr^[I].Hotkey<>0) Do
  954.       With Data[I] Do Begin
  955.         Hotkey.Value:=ResiDataPtr^[I].Hotkey;
  956.         Title.Value:=ConvString(ResiDataPtr^[I].Title);
  957.         Path.Value:=ConvString(ResiDataPtr^[I].Path);
  958.         ProgName.Value:=ConvString(ResiDataPtr^[I].ProgName);
  959.         Inc(I);
  960.       End;
  961.     EntryCount:=I-1;
  962.   End Else Begin
  963.     ResiDataPtr:=Nil;
  964.     EntryCount:=0;
  965.   End;
  966. End;
  967.  
  968. Procedure DeleteEntry(Nr: Byte);         { Eintrag löschen }
  969. Var
  970.   I : Byte;
  971. Begin
  972.   For I:=Nr+1 To EntryCount Do Data[I-1]:=Data[I];
  973.   FillChar(Data[EntryCount], SizeOf(Data[EntryCount]), 0);
  974.   Dec(EntryCount);
  975. End;
  976.  
  977. Procedure TransData;        { Daten an Resident übertragen }
  978. Var
  979.   I : Byte;
  980. Begin
  981.   FillChar(ResiDataPtr^, SizeOf(ResiDataPtr^), 0);
  982.   For I:=1 To MaxEntry Do With Data[I] Do
  983.     If Hotkey.Value<>0 Then Begin
  984.       ResiDataPtr^[I].Hotkey:=Hotkey.Value;
  985.       Move(Title.Value[1], ResiDataPtr^[I].Title,
  986.            Length(Title.Value));
  987.       Move(Path.Value[1], ResiDataPtr^[I].Path,
  988.            Length(Path.Value));
  989.       Move(ProgName.Value[1], ResiDataPtr^[I].ProgName,
  990.            Length(ProgName.Value));
  991.     End;
  992. End;
  993.  
  994. { -- Speichern, Laden ------------------------------------ }
  995.  
  996.                       { Dateinameneingabe-Fenster ausgeben }
  997. Procedure ShowFileInput;
  998. Begin
  999.   SetWindow(WinEdit);
  1000.   SetColor(ColNorm);
  1001.   GotoXY(3, 1); Write('Konfigurationsdatei:');
  1002.   SetColor(ColInverse);
  1003.   GotoXY(25, 3); Write(' Dateinamen akzeptieren ');
  1004. End;
  1005.  
  1006. Type                           { angepaßte Auswahlfunktion }
  1007.   FileChooseObj = Object (ChooseObj)
  1008.                     Constructor Init;
  1009.                     Procedure ReadData; Virtual;
  1010.                     Procedure Close; Virtual;
  1011.                   End;
  1012.  
  1013.                                 { angepaßte Eingabefunktion }
  1014.   FileInputObj = Object (InputObj)
  1015.                    MustExist : Boolean;
  1016.  
  1017.                    Constructor Init;
  1018.                    Function CheckValue: Boolean; Virtual;
  1019.                    Function ManageKey(Ch: Char): Byte;
  1020.                             Virtual;
  1021.                  End;
  1022.  
  1023. Constructor FileChooseObj.Init;     { Auswahl initialieren }
  1024. Begin
  1025.   Status('Bitte wählen Sie die Konfigurationsdatei und '+
  1026.          'betätigen Sie <Return>!');
  1027.   ChooseObj.Init;
  1028. End;
  1029.  
  1030. Procedure FileChooseObj.ReadData;         { Daten einlesen }
  1031. Var
  1032.   F : SearchRec;
  1033. Begin
  1034.   Count:=0;
  1035.                                           { Dateien suchen }
  1036.   FindFirst(CPath+'*.SET', ReadOnly Or Archive, F);
  1037.   While DosError=0 Do Begin
  1038.     Inc(Count);
  1039.     Data[Count]:=F.Name;
  1040.     FindNext(F);
  1041.   End;
  1042.  
  1043.   Count_:=Count;                    { Verzeichnisse suchen }
  1044.   FindFirst(CPath+'*.*', Directory, F);
  1045.   While DosError=0 Do Begin
  1046.     If (F.Attr And Directory<>0) And (F.Name<>'.') Then Begin
  1047.       Inc(Count);
  1048.       Data[Count]:=F.Name+'\';
  1049.     End;
  1050.     FindNext(F);
  1051.   End;
  1052. End;
  1053.  
  1054. Procedure FileChooseObj.Close;  { Auswahlfenster schließen }
  1055. Begin
  1056.   ChooseObj.Close;
  1057.   ShowFileInput;
  1058.   Status('Bitte geben Sie den Dateinamen ein! Wählen mit '+
  1059.          '<Leertaste>');
  1060. End;
  1061.  
  1062. Constructor FileInputObj.Init;    { Eingabe initialisieren }
  1063. Begin
  1064.   MaxLen:=48;
  1065.   X:=25; Y:=1;
  1066.   InputObj.Init;
  1067. End;
  1068.  
  1069.                                  { neue Gültigkeitsprüfung }
  1070. Function FileInputObj.CheckValue: Boolean;
  1071. Var
  1072.   F : SearchRec;
  1073.   S : PathStr;
  1074.   D : DirStr; N : NameStr; E : ExtStr;
  1075. Begin
  1076.   If CutString(Value)='' Then DosError:=0 Else Begin
  1077.     S:=FExpand(CutString(Value));
  1078.     FSplit(S, D, N, E);
  1079.     If E='' Then Begin
  1080.       E:='.SET';
  1081.       S:=S+'.SET';
  1082.     End;
  1083.                             { nur Erweiterung .SET erlaubt }
  1084.     If E<>'.SET' Then DosError:=255 Else
  1085.       FindFirst(S, ReadOnly Or Archive, F);
  1086.   End;
  1087.   If (DosError<>0) And
  1088.      (MustExist Or (DosError<>18)) Then Begin
  1089.     CheckValue:=False;
  1090.     Error('Ungültige Konfigurationsdatei!');
  1091.   End Else CheckValue:=True;
  1092. End;
  1093.  
  1094.                       { erweiterte Tastendruckverarbeitung }
  1095. Function FileInputObj.ManageKey(Ch: Char): Byte;
  1096. Var
  1097.   Res        : Byte;
  1098.   F          : SearchRec;
  1099.   FileChoose : FileChooseObj;
  1100.   S          : String12;
  1101.   P : PathStr; D : DirStr; N : NameStr; E : ExtStr;
  1102. Begin
  1103.   Res:=0;
  1104.   If Ch=' ' Then Begin             { Auswahl bei Leertaste }
  1105.     P:=FExpand(CutString(Value));
  1106.     If P[Length(P)]<>'\' Then Begin
  1107.       FindFirst(P, Directory, F);
  1108.       If (DosError<>0) Or
  1109.          (F.Attr And Directory=0) Then Begin
  1110.         FSplit(P, D, N, E);
  1111.         P:=D;
  1112.       End Else P:=P+'\';
  1113.     End;
  1114.  
  1115.     FindFirst(P+'*.*', AnyFile, F);
  1116.     If Not (DosError In [0, 18]) Then Begin
  1117.       If Length(P)>3 Then Delete(P, Length(P), 1);
  1118.       Error('Verzeichnis '+P+' existiert nicht!');
  1119.       P:=FExpand('');
  1120.     End;
  1121.  
  1122.     FileChoose.CPath:=P;
  1123.     FileChoose.Init;
  1124.     S:=FileChoose.Choose(P);
  1125.     If S<>'' Then Begin
  1126.       Value:=P+S;
  1127.       While Length(Value)<MaxLen Do Value:=Value+' ';
  1128.       Res:=ResNext;
  1129.     End;
  1130.     I:=1;
  1131.   End Else Res:=InputObj.ManageKey(Ch);
  1132.   ManageKey:=Res;
  1133. End;
  1134.  
  1135.                               { Dateinameneingabe-Funktion }
  1136. Function GetFileName(MustExist: Boolean): PathStr;
  1137. Var
  1138.   FileName : PathStr;
  1139.   Bar, Res : Byte;
  1140.   NameOk   : Boolean;         { Flag für "Name akzeptiert" }
  1141.  
  1142. Function GetFileNameEdit: Byte;
  1143. Var
  1144.   FileInput : FileInputObj;
  1145.   D : DirStr; N : NameStr; E : ExtStr;
  1146. Begin
  1147.   Status('Bitte geben Sie den Dateinamen ein! Wählen mit '+
  1148.          '<Leertaste>');
  1149.  
  1150.   SetWindow(WinEdit);
  1151.   FileInput.MustExist:=MustExist;
  1152.   FileInput.Value:=FileName;
  1153.   FileInput.Init;
  1154.   GetFileNameEdit:=FileInput.Edit;
  1155.   FileName:=FileInput.Value;
  1156.   If FileName<>'' Then Begin
  1157.     FileName:=FExpand(FileName);
  1158.     FSplit(FileName, D, N, E);
  1159.     If E='' Then FileName:=FileName+'.SET';
  1160.   End;
  1161. End;
  1162.  
  1163.               { Edit-Funktion für "Dateinamen akzeptieren" }
  1164. Function NameOkEdit: Byte;
  1165. Var
  1166.   Res : Byte;
  1167.   Ch  : Char;
  1168. Begin
  1169.   Status('Bitte drücken Sie <Return> um den Dateinamen zu '+
  1170.          'akzeptieren!');
  1171.   Res:=0;
  1172.   SetColor(ColMarked);
  1173.   GotoXY(25, 3); Write(' Dateinamen akzeptieren ');
  1174.   Repeat
  1175.     Ch:=Readkey;
  1176.     Case Ch Of
  1177.       #0: Case Readkey Of
  1178.             'H': Res:=ResPrev;
  1179.             'P': Res:=ResNext;
  1180.           End;
  1181.       #13: Begin NameOk:=True; Res:=ResNext; End;
  1182.     End;
  1183.   Until Res<>0;
  1184.   NameOkEdit:=Res;
  1185. End;
  1186.  
  1187. Begin
  1188.   NameOk:=False;
  1189.   FileName:=''; Bar:=1;
  1190.   Repeat
  1191.     ShowFileInput;               { Eingabefenster anzeigen }
  1192.     SetColor(ColHigh);
  1193.     GotoXY(25, 1); Write(FileName, '':48-Length(FileName));
  1194.  
  1195.     Case Bar Of
  1196.       1: Begin
  1197.            Res:=GetFileNameEdit;
  1198.            If Res=ResNext Then Bar:=2;
  1199.          End;
  1200.       2: Begin
  1201.            Res:=NameOkEdit;
  1202.            If Res=ResPrev Then Bar:=1;
  1203.          End;
  1204.     End;
  1205.   Until NameOk;
  1206.   SetColor(ColNorm); ClrScr;
  1207.   GetFileName:=FileName;
  1208. End;
  1209.  
  1210.                   { Daten in Konfigurationsdatei speichern }
  1211. Procedure SaveFile;
  1212.  
  1213.                                   { Word in Hex darstellen }
  1214. Function HexWord(W: Word): String4;
  1215. Const
  1216.   HexCode: Array[0..15] Of Char = '0123456789ABCDEF';
  1217. Begin
  1218.   HexWord:=HexCode[Hi(W) Shr 4]+HexCode[Hi(W) And $F]+
  1219.            HexCode[Lo(W) Shr 4]+HexCode[Lo(W) And $F];
  1220. End;
  1221.  
  1222. Var
  1223.   F     : Text;
  1224.   FName : PathStr;
  1225.   I     : Byte;
  1226. Begin
  1227.   FName:=GetFileName(False);
  1228.   If FName<>'' Then Begin
  1229.     Assign(F, FName);
  1230.     Rewrite(F);
  1231.     For I:=1 To EntryCount Do With Data[I] Do
  1232.       Writeln(F, HexWord(Hotkey.Value), ';', Title.Value,
  1233.               ';', Path.Value, ';', ProgName.Value);
  1234.     Close(F);
  1235.   End;
  1236. End;
  1237.  
  1238. Procedure LoadFile;            { Konfigurationsdatei laden }
  1239. Var
  1240.   F     : Text;
  1241.   FName : PathStr;
  1242.   I, P  : Byte;
  1243.   S, S1 : String;
  1244.   Code  : Integer;
  1245. Begin
  1246.   FName:=GetFileName(True);
  1247.   If FName<>'' Then Begin
  1248.     Assign(F, FName);
  1249.     Reset(F);
  1250.     FillChar(Data, SizeOf(Data), 0);
  1251.     For I:=1 To MaxEntry Do Data[I].Number:=I;
  1252.     I:=1;
  1253.     While Not Eof(F) Do Begin
  1254.       Readln(F, S);
  1255.       With Data[I] Do Begin
  1256.         P:=Pos(';', S);
  1257.         S1:=Copy(S, 1, P-1);
  1258.         Val('$'+S1, Hotkey.Value, Code);
  1259.         Delete(S, 1, P);
  1260.  
  1261.         P:=Pos(';', S);
  1262.         Title.Value:=Copy(S, 1, P-1);
  1263.         Delete(S, 1, P);
  1264.  
  1265.         P:=Pos(';', S);
  1266.         Path.Value:=Copy(S, 1, P-1);
  1267.         Delete(S, 1, P);
  1268.  
  1269.         ProgName.Value:=S;
  1270.       End;
  1271.       Inc(I);
  1272.     End;
  1273.     EntryCount:=I-1;
  1274.     Close(F);
  1275.   End;
  1276. End;
  1277.  
  1278. Procedure ManageFunctions;          { Hauptmenü-Verwaltung }
  1279.  
  1280. Procedure GetFunction(Var Bar: Byte); { Menüpunkt anwählen }
  1281. Const
  1282.   Functions : Array[1..9] Of String[15] =
  1283.   ('Zurück', 'Vor', 'Edit', 'Löschen', 'Neu', 'Übertragen',
  1284.    'Speichern', 'Laden', 'Ende');
  1285. Var
  1286.   I  : Byte;
  1287.   Ch : Char;
  1288. Begin
  1289.   SetWindow(WinMain);
  1290.   SetColor(ColNorm);
  1291.   Status('Bitte wählen Sie eine Funktion!');
  1292.   Repeat
  1293.     GotoXY(5, 1);
  1294.     For I:=1 To 9 Do Begin
  1295.       If I=Bar Then SetColor(ColMarked) Else
  1296.         SetColor(ColInverse);
  1297.       Write(' ', Functions[I], ' ');
  1298.     End;
  1299.     Ch:=Readkey;
  1300.     If Ch=#0 Then Case Readkey Of
  1301.       'K': If Bar>1 Then Dec(Bar) Else Bar:=9;
  1302.       'M': If Bar<9 Then Inc(Bar) Else Bar:=1;
  1303.     End;
  1304.   Until Ch=#13;
  1305. End;
  1306.  
  1307. Var
  1308.   Bar, ActEntry : Byte;
  1309.  
  1310. Begin
  1311.   If EntryCount=0 Then ActEntry:=0 Else ActEntry:=1;
  1312.   Data[ActEntry].Show;
  1313.   Bar:=1;
  1314.   Repeat
  1315.     GetFunction(Bar);
  1316.     Case Bar Of
  1317.       1: If ActEntry>1 Then Begin                 { Zurück }
  1318.            Dec(ActEntry); Data[ActEntry].Show;
  1319.          End Else Error('Kein weiterer Eintrag vorhanden!');
  1320.       2: If ActEntry<EntryCount Then Begin           { Vor }
  1321.            Inc(ActEntry); Data[ActEntry].Show;
  1322.          End Else Error('Kein weiterer Eintrag vorhanden!');
  1323.       3: If ActEntry>0 Then                         { Edit }
  1324.            Data[ActEntry].Edit
  1325.          Else Error('Kein Eintrag vorhanden!');
  1326.       4: If ActEntry>0 Then Begin                { Löschen }
  1327.            DeleteEntry(ActEntry);
  1328.            If ActEntry>EntryCount Then ActEntry:=EntryCount;
  1329.            Data[ActEntry].Show;
  1330.          End Else Error('Kein Eintrag vorhanden!');
  1331.       5: If EntryCount<MaxEntry Then Begin           { Neu }
  1332.            Inc(EntryCount);
  1333.            ActEntry:=EntryCount;
  1334.            Data[ActEntry].Edit;
  1335.          End Else Error('Keine weiteren Einträge möglich!');
  1336.       6: If ResiDataPtr<>Nil Then Begin       { Übertragen }
  1337.            TransData;
  1338.            If EntryCount=0 Then ActEntry:=0 Else
  1339.              ActEntry:=1;
  1340.            Data[ActEntry].Show;
  1341.          End Else Error('Resident ist nicht installiert!');
  1342.       7: Begin                                 { Speichern }
  1343.            SaveFile;
  1344.            If EntryCount=0 Then ActEntry:=0 Else
  1345.              ActEntry:=1;
  1346.            Data[ActEntry].Show;
  1347.          End;
  1348.       8: Begin                                     { Laden }
  1349.            LoadFile;
  1350.            If EntryCount=0 Then ActEntry:=0 Else
  1351.              ActEntry:=1;
  1352.            Data[ActEntry].Show;
  1353.          End;
  1354.     End;
  1355.   Until Bar=9;
  1356. End;
  1357.  
  1358. Begin { Hauptprogramm }
  1359.   ExitSav:=ExitProc;      { neue Exit-Routine installieren }
  1360.   ExitProc:=@CloseScreen;
  1361.   InitScreen;
  1362.   GetData;
  1363.   ManageFunctions;
  1364. End.