home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1989 / 06 / praxis / fselect.mod < prev    next >
Encoding:
Modula Implementation  |  1989-03-23  |  14.5 KB  |  500 lines

  1. (*********************************************************)
  2. (*                      FSELECT.MOD                      *)
  3. (*          Dateiauswahlbox für TopSpeed Modula 2        *)
  4. (*              (C) 1989 Dirk Donath & TOOLBOX           *)
  5. (*********************************************************)
  6.  
  7. IMPLEMENTATION MODULE FSelect;
  8.  
  9. FROM SYSTEM  IMPORT Registers;
  10. FROM FIO     IMPORT ReadFirstEntry,PathTail,FileAttr,
  11.                     directory,DirEntry,
  12.                     ReadNextEntry,ChDir,GetDir,
  13.                     IOcheck,IOresult;
  14. FROM IO      IMPORT WrStr,WrStrAdj,RdKey,RdStr;
  15. FROM Str     IMPORT Append,Compare,Pos,Delete,Length,
  16.                     Concat,Caps,Insert,Match,Copy;
  17. FROM Window  IMPORT WinDef,WinType,Color,Open,DoubleFrame,
  18.                     GotoXY,ClrEol,Close,TextColor,
  19.                     TextBackground,Clear,SetTitle,
  20.                     TitleMode,WhereX;
  21. FROM Lib     IMPORT Dos,QSort;
  22.  
  23. CONST MaxEintraege = 200;
  24.  
  25. TYPE String12    = ARRAY[0..12] OF CHAR;
  26.      EintragsTyp = ARRAY[1..MaxEintraege] OF String12;
  27.  
  28. VAR DirectoryGewaehlt,ErstesMal,
  29.     WildCards,SuchwegGefunden      : BOOLEAN;
  30.     LWNummer                       : SHORTCARD;
  31.     AnzEintraege,EintragsIndex,i   : CARDINAL;
  32.     Dir,Maske,DateiMaske           : ARRAY[0..40] OF CHAR;
  33.     AltesLaufwerk,NeuesLaufwerk    : ARRAY[0..3] OF CHAR;
  34.     AlterPfad,NeuerPfad            : ARRAY[0..40] OF CHAR;
  35.     Eintrag                        : EintragsTyp;
  36.     DF                             : WinDef;
  37.     DateiFenster                   : WinType;
  38.  
  39. (*========================================================*)
  40. (*  Bestimmung des aktuellen Laufwerks  (A=1,B=2,C=3 etc.)*)
  41. (*========================================================*)
  42.  
  43. PROCEDURE GetDrive() : SHORTCARD ;
  44.  
  45. VAR r : Registers;
  46.  
  47. BEGIN
  48.   r.AH := 19H ;
  49.   Dos(r);
  50.   RETURN r.AL+1 ;
  51. END GetDrive ;
  52.  
  53. (*========================================================*)
  54. (*          Hilfsprozeduren für das Sortieren             *)
  55. (*========================================================*)
  56.  
  57. PROCEDURE Less(i,j : CARDINAL) : BOOLEAN;
  58.  
  59. BEGIN
  60.   RETURN Compare(Eintrag[i],Eintrag[j]) < 0;
  61. END Less;
  62.  
  63. PROCEDURE Swap(i,j : CARDINAL);
  64.  
  65. VAR temp : String12;
  66.  
  67. BEGIN
  68.   temp       := Eintrag[i];
  69.   Eintrag[i] := Eintrag[j];
  70.   Eintrag[j] := temp;
  71. END Swap;
  72.  
  73. (*========================================================*)
  74. (*                 Hauptprozedur                          *)
  75. (*========================================================*)
  76.  
  77. PROCEDURE GetFName(Frage : FraTyp; Antwort : AntTyp;
  78.                    VAR DateiName : ARRAY OF CHAR) : BOOLEAN;
  79.  
  80. (*--------------------------------------------------------*)
  81. (*  Erfragen eines Dateinamens bzw. einer Directory-Maske *)
  82. (*--------------------------------------------------------*)
  83.  
  84. PROCEDURE ErfrageMaske;
  85.  
  86. VAR  AlteLWNummer : SHORTCARD;
  87.      StartPos,i   : CARDINAL;
  88.      Dummy        : CHAR;
  89.      FF           : WinDef;
  90.      FrageFenster : WinType;
  91.  
  92. BEGIN
  93.   SuchwegGefunden := TRUE;
  94.   AlteLWNummer    := GetDrive();
  95.   CASE AlteLWNummer OF
  96.   | 1: AltesLaufwerk := 'A:\';
  97.   | 2: AltesLaufwerk := 'B:\';
  98.   | 3: AltesLaufwerk := 'C:\';
  99.   | 4: AltesLaufwerk := 'D:\';
  100.   | 5: AltesLaufwerk := 'E:\';
  101.   | 6: AltesLaufwerk := 'F:\';
  102.   END;
  103.   GetDir(AlteLWNummer,AlterPfad);
  104.   (* Führender \ muß weg, da er schon Bestandteil
  105.      der Laufwerkskennung ist:                    *)
  106.   IF AlterPfad[0] = '\' THEN
  107.     Delete(AlterPfad,0,1);
  108.   END;
  109.   Concat(AlterPfad,AltesLaufwerk,AlterPfad);
  110.   ErstesMal := TRUE;   (* Flag für das Directory-Fenster *)
  111.   WITH FF DO
  112.     X1 := Frage.X1;(* Frage-Fenster definieren u. öffnen *)
  113.     Y1 := Frage.Y1;
  114.     X2 := 2+Frage.Breite;
  115.     Y2 := Y1+2;
  116.     Foreground := LightGray;
  117.     Background := Black;
  118.     CursorOn   := TRUE;
  119.     WrapOn     := FALSE;
  120.     FrameOn    := TRUE;
  121.     FrameDef   := DoubleFrame;
  122.     FrameFore  := LightGray;
  123.     FrameBack  := Black;
  124.     Hidden     := FALSE;
  125.   END;
  126.   FrageFenster := Open(FF);
  127.   GotoXY(2,1);
  128.   WrStr(Frage.Prompt);
  129.   GotoXY(WhereX()+1,1);
  130.   RdStr(Maske);
  131.   IF ((Maske[1] = ':') AND (Maske[2] <> '\')) THEN
  132.     Insert(Maske,'\',2);
  133.   END;
  134.   Dir        := Maske;
  135.   DateiMaske := Maske;
  136.   IF Pos(Maske,'.') < 65000 THEN   (* Der Punkt kommt vor *)
  137.     StartPos := 0;
  138.     FOR i := 0 TO Length(Maske) DO
  139.       IF (Maske[i] = '\') THEN StartPos := i+1; END;
  140.      (* StartPos = Position des letzten \ im String Maske *)
  141.     END;
  142.     IF StartPos > 0 THEN
  143.       IF (((Maske[1] = ':')
  144.            AND (StartPos < 4)) OR (StartPos=1)) THEN
  145.         Delete(Dir,StartPos,12);    (* F. Hauptdirectory \*)
  146.       ELSE                          (* erhalten           *)
  147.         Delete(Dir,StartPos-1,12);  (* sonst muß er weg   *)
  148.       END;
  149.       Delete(DateiMaske,0,StartPos);(* Dateimaske entfernen *)
  150.       IOcheck := FALSE;
  151.       ChDir(Dir);
  152.       IOcheck := TRUE;
  153.       IF IOresult() <> 0 THEN
  154.         SuchwegGefunden := FALSE;
  155.         Clear;
  156.         GotoXY(2,1);
  157.         WrStr('Suchweg nicht gefunden');
  158.         Dummy := RdKey();
  159.       END;
  160.     END;
  161.   END;
  162.   IF ((Pos(DateiMaske,'?') > 65000)
  163.       AND (Pos(DateiMaske,'*') > 65000)) THEN
  164.     WildCards := FALSE;
  165.   ELSE
  166.     WildCards := TRUE;
  167.   END;
  168.   Close(FrageFenster);
  169. END ErfrageMaske;
  170.  
  171. (*--------------------------------------------------------*)
  172. (*               Lesen des Directorys                     *)
  173. (*--------------------------------------------------------*)
  174.  
  175. PROCEDURE LeseDirectory;
  176.  
  177. VAR DE : DirEntry;
  178.  
  179. (* Verarbeiten eines Directory-Eintrags  *)
  180.  
  181. PROCEDURE VerarbeiteEintrag;
  182.  
  183. VAR
  184.   i           : CARDINAL;
  185.   HilfsString : String12;
  186.  
  187. BEGIN
  188.   Copy(HilfsString,DE.Name);
  189.   (* Eintrag '.' wird nicht aufgenommen. Der Eintrag
  190.      muß in die Maske DateiMaske passen oder ein
  191.      Directory sein:                                     *)
  192.   IF ((Compare(HilfsString,'.') <> 0) AND
  193.       ((Match(HilfsString,DateiMaske))
  194.         OR (directory IN DE.attr))) THEN
  195.     INC(AnzEintraege);
  196.     IF AnzEintraege > MaxEintraege THEN
  197.       AnzEintraege := MaxEintraege;
  198.     END;
  199.     Eintrag[AnzEintraege] := HilfsString;
  200.   END;
  201.   (* Kennzeichnung eines Directorys durch angehängten \ : *)
  202.   IF directory IN DE.attr THEN
  203.     Append(Eintrag[AnzEintraege],'\');
  204.   END;
  205. END VerarbeiteEintrag;
  206.  
  207. BEGIN  (* LeseDirectory *)
  208.   AnzEintraege := 0;
  209.   IF ReadFirstEntry('*.*',FileAttr{directory},DE) THEN
  210.     VerarbeiteEintrag;
  211.     WHILE ReadNextEntry(DE) DO
  212.       VerarbeiteEintrag;
  213.     END;
  214.     IF AnzEintraege > 1 THEN
  215.       QSort(AnzEintraege,Less,Swap);   (* Alphabet. Sort. *)
  216.     END;
  217.   END;
  218. END LeseDirectory;
  219.  
  220. (*--------------------------------------------------------*)
  221. (*         Directory-Ausgabe und Menueauswahl             *)
  222. (*--------------------------------------------------------*)
  223.  
  224. PROCEDURE Menue(VAR Index : CARDINAL);
  225.  
  226. VAR  FunktionsTaste                         : BOOLEAN;
  227.      x,y,i,ScrollZaehler,AlterScrollZaehler : CARDINAL;
  228.      Taste                                  : CHAR;
  229.  
  230. PROCEDURE Lesen(VAR Taste : CHAR; VAR Funkcode : BOOLEAN);
  231.  
  232. VAR  Tas : CHAR;
  233.  
  234. BEGIN
  235.   Tas:=RdKey();
  236.   IF Tas=0C THEN
  237.     Tas:=RdKey();
  238.     Funkcode:=TRUE;
  239.   ELSE
  240.     Funkcode:=FALSE;
  241.   END;
  242.   Taste:=Tas;
  243. END Lesen;
  244.  
  245. PROCEDURE XPos(i : CARDINAL) : CARDINAL;
  246.  
  247. BEGIN
  248.   RETURN ((i-1) MOD Antwort.Spalten) * 14 + 2;
  249. END XPos;
  250.  
  251. PROCEDURE YPos(i : CARDINAL) : CARDINAL;
  252.  
  253. BEGIN
  254.   RETURN ((i-1) DIV Antwort.Spalten) + 1;
  255. END YPos;
  256.  
  257. PROCEDURE EintragsNummer(x,y : CARDINAL) : CARDINAL;
  258.  
  259. BEGIN
  260.   RETURN x + Antwort.Spalten * (y-1);
  261. END EintragsNummer;
  262.  
  263. PROCEDURE SchreibeDateiname(x,y : CARDINAL);
  264.  
  265. VAR i : CARDINAL;
  266.  
  267. BEGIN
  268.   i := EintragsNummer(x,y);
  269.   GotoXY(XPos(i),YPos(i));
  270.   WrStrAdj(Eintrag[i + Antwort.Spalten
  271.                        * ScrollZaehler],-13);
  272. END SchreibeDateiname;
  273.  
  274. BEGIN  (* Menue *)
  275.   FOR i := 1 TO AnzEintraege DO
  276.     IF YPos(i) <= Antwort.Zeilen THEN
  277.       GotoXY(XPos(i),YPos(i));
  278.       WrStrAdj(Eintrag[i],-13);
  279.       (* Ausgabe der Einträge, soweit sichtbar *)
  280.     END;
  281.   END;
  282.   ScrollZaehler := 0;   (* Es wurde noch nicht gescrollt *)
  283.   x             := 1;   (* Logische x- und               *)
  284.   y             := 1;   (* y-Positionen                  *)
  285.   TextColor(Black);
  286.   TextBackground(LightGray);
  287.   SchreibeDateiname(x,y);
  288.            (* Hervorgehobene Darstellung des 1. Eintrags *)
  289.   REPEAT  (* UNTIL RETURN OR ESC *)
  290.     REPEAT
  291.       Lesen(Taste,FunktionsTaste);
  292.     UNTIL (((FunktionsTaste) AND ((Taste = CHAR(72)) OR
  293.                                   (Taste = CHAR(80)) OR
  294.                                   (Taste = CHAR(75)) OR
  295.                                   (Taste = CHAR(77)))
  296.            OR (Taste=CHAR(13)) OR (Taste = CHAR(27))));
  297.     AlterScrollZaehler := ScrollZaehler;
  298.     TextColor(LightGray);
  299.     TextBackground(Black);
  300.     SchreibeDateiname(x,y);  (* Hervorhebung Alt aus *)
  301.     CASE Taste OF
  302.     | CHAR(80): (* runter *)
  303.         IF (EintragsNummer(1,y+1)+Antwort.Spalten
  304.             *ScrollZaehler <= AnzEintraege) THEN
  305.           IF (EintragsNummer(x,y+1)+Antwort.Spalten
  306.               *ScrollZaehler > AnzEintraege) THEN
  307.             x := (AnzEintraege-1) MOD Antwort.Spalten + 1;
  308.           END;
  309.           IF y<Antwort.Zeilen THEN
  310.             INC(y)
  311.           ELSE
  312.             INC(ScrollZaehler);
  313.           END;
  314.         END;
  315.     | CHAR(72): (* rauf *)
  316.         IF y > 1 THEN
  317.           DEC(y)
  318.         ELSE
  319.           IF ScrollZaehler > 0 THEN
  320.             DEC(ScrollZaehler);
  321.           END;
  322.         END;
  323.     | CHAR(75): (* links *)
  324.         IF x > 1 THEN
  325.           DEC(x);
  326.         END;
  327.     | CHAR(77): (* rechts *)
  328.         IF ((x < Antwort.Spalten) AND
  329.             (EintragsNummer(x+1,y)+Antwort.Spalten
  330.              *ScrollZaehler <= AnzEintraege)) THEN
  331.           INC(x);
  332.         END;
  333.     END;  (* CASE *)
  334.     IF ScrollZaehler <> AlterScrollZaehler THEN(* Scrollen*)
  335.       FOR i := Antwort.Spalten*ScrollZaehler+1
  336.                TO AnzEintraege DO
  337.         IF (YPos(i) - ScrollZaehler <= Antwort.Zeilen) THEN
  338.           GotoXY(XPos(i),YPos(i) - ScrollZaehler);
  339.           WrStrAdj(Eintrag[i],-13);
  340.         END;
  341.       END;
  342.       ClrEol;
  343.     END;
  344.     TextColor(Black);
  345.     TextBackground(LightGray);
  346.     SchreibeDateiname(x,y);  (* Neuen Eintrag hervorheben *)
  347.   UNTIL ((Taste = CHAR(13)) OR (Taste = CHAR(27)));
  348.   TextColor(LightGray);
  349.   TextBackground(Black);
  350.   IF Taste = CHAR(27) THEN
  351.     Index := 0
  352.   ELSE
  353.     (* Nummer des aktuellen Eintrags wird zurückgegeben: *)
  354.     Index := EintragsNummer(x,y)
  355.              + Antwort.Spalten * ScrollZaehler;
  356.   END;
  357. END Menue;
  358.  
  359. (*--------------------------------------------------------*)
  360. (*    Definition und Ausgabe des Directory-Fensters       *)
  361. (*--------------------------------------------------------*)
  362.  
  363. PROCEDURE FensterAusgabe;
  364.  
  365. VAR  i                    : CARDINAL;
  366.      Dir                  : String12;
  367.      TitelString,PfadName : ARRAY[0..40] OF CHAR;
  368.      Dummy                : CHAR;
  369.  
  370. BEGIN
  371.   IF ErstesMal THEN   (* Fenster definieren und eröffnen *)
  372.     ErstesMal := FALSE;
  373.     WITH DF DO
  374.       X1         := Antwort.X1;
  375.       Y1         := Antwort.Y1;
  376.       X2         := X1 + 14 * Antwort.Spalten + 2;
  377.       Y2         := Y1 + Antwort.Zeilen + 1;
  378.       Foreground := LightGray;
  379.       Background := Black;
  380.       CursorOn   := FALSE;
  381.       WrapOn     := FALSE;
  382.       FrameOn    := TRUE;
  383.       FrameDef   := DoubleFrame;
  384.       FrameFore  := LightGray;
  385.       FrameBack  := Black;
  386.       Hidden     := FALSE;
  387.     END;
  388.     DateiFenster := Open(DF);
  389.   END;
  390.   (* Laufwerk u. Directory ermitteln: *)
  391.   LWNummer := GetDrive();
  392.   CASE LWNummer OF
  393.   | 1: NeuesLaufwerk := 'A:\';
  394.   | 2: NeuesLaufwerk := 'B:\';
  395.   | 3: NeuesLaufwerk := 'C:\';
  396.   | 4: NeuesLaufwerk := 'D:\';
  397.   | 5: NeuesLaufwerk := 'E:\';
  398.   | 6: NeuesLaufwerk := 'F:\';
  399.   END;
  400.   GetDir(LWNummer,PfadName);
  401.   (* Titel zusammenbasteln: *)
  402.   Concat(TitelString,' ',NeuesLaufwerk);
  403.   IF PfadName[0] = '\' THEN
  404.     Delete(PfadName,0,1);  (* Führenden \ entfernen *)
  405.   END;
  406.   Append(TitelString,PfadName);
  407.   IF TitelString[Length(TitelString)-1] <> '\' THEN
  408.     Append(TitelString,'\');(* String mit \ enden lassen *)
  409.   END;
  410.   Append(TitelString,DateiMaske);
  411.   Append(TitelString,' ');
  412.   Caps(TitelString);
  413.   SetTitle(DateiFenster,TitelString,CenterUpperTitle);
  414.   IF AnzEintraege > 0 THEN
  415.     Menue(EintragsIndex);(* Menüroutine liefert Index *)
  416.   ELSE
  417.     GotoXY(1,1);
  418.     WrStr('Datei nicht gefunden');
  419.     EintragsIndex := 0;
  420.     Dummy := RdKey();
  421.   END;
  422.   Clear;
  423.   IF EintragsIndex > 0 THEN
  424.     (* Das Menü wurde mit RETURN verlassen  *)
  425.     IF Pos(Eintrag[EintragsIndex],'\') < 65000 THEN
  426.       DirectoryGewaehlt := TRUE;
  427.       Dir               := Eintrag[EintragsIndex];
  428.       Delete(Dir,Length(Dir)-1,1);  (*  '\' entfernen    *)
  429.       ChDir(Dir);                   (* Directory wechseln*)
  430.       Clear;
  431.     ELSE
  432.       DirectoryGewaehlt := FALSE;
  433.       Close(DateiFenster);
  434.     END;
  435.   ELSE
  436.     Close(DateiFenster);
  437.   END;
  438. END FensterAusgabe;
  439.  
  440. (*--------------------------------------------------------*)
  441. (*     Ermittlung des gewählten Laufwerks/Pfades          *)
  442. (*--------------------------------------------------------*)
  443.  
  444. PROCEDURE ErmittlePfadname;
  445.  
  446. BEGIN
  447.   LWNummer := GetDrive();
  448.   CASE LWNummer OF
  449.   | 1: NeuesLaufwerk := 'A:\';
  450.   | 2: NeuesLaufwerk := 'B:\';
  451.   | 3: NeuesLaufwerk := 'C:\';
  452.   | 4: NeuesLaufwerk := 'D:\';
  453.   | 5: NeuesLaufwerk := 'E:\';
  454.   | 6: NeuesLaufwerk := 'F:\';
  455.   END;
  456.   GetDir(LWNummer,NeuerPfad);
  457.   IF NeuerPfad[0] = '\' THEN
  458.     Delete(NeuerPfad,0,1);  (* Führenden \ entfernen *)
  459.   END;
  460.   Concat(NeuerPfad,NeuesLaufwerk,NeuerPfad);
  461.   (* Pfadname muß mit \ aufhören, da später
  462.      der Dateiname angehängt wird:             *)
  463.   IF NeuerPfad[Length(NeuerPfad)-1] <> '\' THEN
  464.     Append(NeuerPfad,'\');
  465.   END;
  466.   ChDir(AlterPfad);
  467.   (* Wiederherstellung des alten Pfades vor Prog.ende *)
  468. END ErmittlePfadname;
  469.  
  470. (*--------------------------------------------------------*)
  471.  
  472. BEGIN  (* GetFName *)
  473.   ErfrageMaske;
  474.   IF SuchwegGefunden THEN
  475.     IF WildCards THEN
  476.       REPEAT
  477.         LeseDirectory;
  478.         FensterAusgabe;
  479.       UNTIL ((EintragsIndex=0) OR (NOT DirectoryGewaehlt));
  480.       ErmittlePfadname;
  481.       IF EintragsIndex=0 THEN
  482.         RETURN FALSE;
  483.       ELSE
  484.         Copy(DateiName,Eintrag[EintragsIndex]);
  485.         Concat(DateiName,NeuerPfad,DateiName);
  486.         RETURN TRUE;
  487.       END;
  488.     ELSE
  489.       ErmittlePfadname;
  490.       Copy(DateiName,DateiMaske);
  491.       Concat(DateiName,NeuerPfad,DateiName);
  492.       RETURN TRUE;
  493.     END;
  494.   ELSE
  495.     RETURN FALSE;
  496.   END;
  497. END GetFName;
  498.  
  499. END FSelect.
  500.