home *** CD-ROM | disk | FTP | other *** search
- (* ----------------------------------------------------------------------- *)
- (* DIRMT.PSP *)
- (* (c) 1987 Michael Ceol & PASCAL INT. *)
- (* System- und Compiler-spezifischer Teil der Directory-Bibliothek fuer *)
- (* ATARI TOS in Pascal ST Plus *)
- (* programmiert und getestet auf einem ST 1040 mit ROM-BS *)
- (* ----------------------------------------------------------------------- *)
- (* neue DTA-Adresse setzen bzw. aktuelle DTA-Adresse holen: *)
- PROCEDURE FSetDTA (DTA: DTA_Ptr); GEMDOS($1A);
- FUNCTION FGetDTA: DTA_Ptr; GEMDOS($2F);
- (* ----------------------------------------------------------------------- *)
- (* ersten Directory-Eintrag bzw. naechsten suchen: *)
- FUNCTION FSFirst (VAR search: Dir_Chr0; attr: INTEGER): INTEGER; GEMDOS($4E);
- FUNCTION FSNext: INTEGER; GEMDOS($4F);
- (* ----------------------------------------------------------------------- *)
- (* ----------------------------------------------------------------------- *)
- (* drei Compiler-abhaengige Bit-Funktionen: *)
- (* Die Bits von "value" um "n" Stellen nach rechts shiften (verschieben): *)
- FUNCTION ShiftR (value, n: INTEGER): INTEGER;
- BEGIN ShiftR := SHR(value,n) END;
- (* Die Bits von "value" um "n" Stellen nach links shiften: *)
- FUNCTION ShiftL (value, n: INTEGER): INTEGER;
- BEGIN ShiftL := SHL(value,n) END;
- (* Die Bits von "val1" und "val2" undieren: *)
- FUNCTION AndInt (val1, val2: INTEGER): INTEGER;
- BEGIN AndInt := val1 & val2 END;
- (* ----------------------------------------------------------------------- *)
- (* nochmal zwei eventuell anzupassende Routinen, die hier aber fuer *)
- (* Turbo Pascal und Pascal ST Plus gleich sind: *)
- (* Integer-Wert zu einer 'n'-stelligen Zeichenkette mit fuehrenden Nullen: *)
- PROCEDURE IntStr (value, n: INTEGER; VAR s: Dir_Str);
- VAR i : INTEGER; Ch: CHAR;
- BEGIN
- s := '';
- FOR i := 1 TO n DO BEGIN
- s := Concat(Chr((value MOD 10)+Ord('0')),s); value := value DIV 10;
- END;
- END;
- (* wg. negativen Integer-Werten bei grossen Dateigroessen selbigen Wert zu *)
- (* einem positiven Real-Wert konvertieren: *)
- FUNCTION IntCard (i: INTEGER): REAL;
- BEGIN IF i < 0 THEN IntCard := 65536.0 + i ELSE IntCard := i; END;
- (* ----------------------------------------------------------------------- *)
- (* Pascal ST Plus kennt die UpCase-Funktion nicht: *)
- FUNCTION UpCase (ch: CHAR): CHAR;
- BEGIN UpCase := ch; IF ch IN ['a'..'z'] THEN UpCase := Chr(Ord(ch)-32); END;
- (* ----------------------------------------------------------------------- *)
- (* ----------------------------------------------------------------------- *)
- (* liefert einen Bitvektor, der durch 16 Bits die angemeldeten Laufwerke *)
- (* repraesentiert. Bit 0 = Laufwerk A, Bit 1 = Laufwerk B usw. Entsp. Bit *)
- (* gesetzt -> Laufwerk vorhanden, sonst nicht. *)
- FUNCTION DrvMap: INTEGER;
- (* TOS liefert einen 32-Bit-Vektor, der einfach auf 16 Bit gekuerzt wird *)
- FUNCTION DoDrvMap: LONG_INTEGER; BIOS(10);
- BEGIN DrvMap := Trunc(DoDrvMap * 1.0); END;
- (* ----------------------------------------------------------------------- *)
- (* aktuelles Laufwerk ermitteln (0 = A, 1 = B, 2 = C usw.): *)
- FUNCTION DGetDrive: INTEGER; GEMDOS($19);
-
- (* neues Laufwerk setzen (0 = A, 1 = B, 2 = C usw.): *)
- FUNCTION DSetDrive (drive: INTEGER): INTEGER;
- (* BS-Funktion, gibt das zuvor angemeldete Laufwerk zurueck: *)
- FUNCTION DoSetDrive (drive: INTEGER): INTEGER; GEMDOS($0E);
- BEGIN
- (* wenn Laufwerk nicht vorhanden, dann Fehler zurueckmelden: *)
- IF AndInt(DrvMap,ShiftL(1,drive)) = 0 THEN DSetDrive := DOSedriv
- ELSE BEGIN DSetDrive := DoSetDrive(drive); DSetDrive := DOSfnok; END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* Pfadspezifikation aus fspec extrahieren und in fpath zurueckgeben. Da- *)
- (* bei findet keine Ueberpruefung auf Korrektheit des Pfades statt!. next- *)
- (* ch zeigt auf das erste, dem Pfad folgende Zeichen des Dateinamens. *)
- PROCEDURE FGetPath (VAR fspec, fpath: Dir_Chr0; VAR nextch: INTEGER);
- VAR cont: BOOLEAN;
- BEGIN
- nextch := 0; cont := TRUE;
- REPEAT
- nextch := Succ(nextch); fpath[nextch] := UpCase(fspec[nextch]);
- UNTIL fspec[nextch] = Chr(0);
- WHILE cont DO BEGIN
- cont := NOT (fpath[nextch] IN [':','\']);
- IF cont THEN BEGIN
- fpath[nextch] := Chr(0); nextch := Pred(nextch); cont := nextch > 0;
- END;
- END;
- nextch := Succ(nextch);
- END;
-
- (* Dateinamen wie z.B. "A:*.pas" untersuchen und in der Form "1????????PAS"*)
- (* im File Control Block "DirFCB" eintragen sowie weitere Initialisier- *)
- (* ungen in selbigem treffen. result = 0 -> fname war ok, result = 1 -> *)
- (* fname enthaelt "*" oder "?", result = 255 -> fname fehlerhaft. nextch *)
- (* zeigt auf das erste, nicht mehr zum Dateinamen gehoerende Zeichen. *)
- (* Diese Prozedur sollte fuer Dateispez. mit Pfad nicht benutzt werden!!! *)
- PROCEDURE FParsName (VAR fname: Dir_Chr0; VAR nextch, result: INTEGER);
- LABEL 999;
- VAR i: INTEGER; delimiters: SET OF CHAR; fstr: Dir_Str;
-
- PROCEDURE fpart; (* einen Teil (Laufwerk, Dateiname...) abteilen *)
- BEGIN
- fstr := ''; nextch := Succ(nextch);
- WHILE (NOT (fname[nextch] IN delimiters)) AND (fname[nextch] <> Chr(0))
- DO BEGIN
- IF fname[nextch] IN ['*','?'] THEN result := 1;
- fstr := Concat(fstr,UpCase(fname[nextch])); nextch := Succ(nextch);
- END;
- END;
-
- BEGIN
- delimiters := [];
- FOR i := 1 TO 32 DO delimiters := delimiters + [Chr(i)];
- delimiters := delimiters + [';', '=', '+', '.', ':', ','];
- result := 0;
- nextch := 1; (* fuehrende Trennzeichen entfernen: *)
- WHILE (fname[nextch] IN delimiters) AND (fname[nextch] <> Chr(0)) DO
- nextch := Succ(nextch);
- nextch := Pred(nextch);
- fpart; (* ersten Teil des Dateinamens trennen *)
- delimiters := delimiters + ['<', '>', '[', ']', '|', '/', '\', '"'];
- IF (fname[nextch] = ':') AND (Length(fstr) = 1) THEN (* Laufwerksangabe? *)
- IF fstr[1] IN ['A'..'P'] THEN fpart (* ja. Naechsten Teil abtrennen *)
- ELSE BEGIN result := 255; GOTO 999; END; (* ungueltiges Laufwerk!*)
- IF Length(fstr) <= 8 THEN (* ordentlicher Dateiname ? *)
- BEGIN
- IF fname[nextch] = '.' THEN (* kommt noch Erweiterung ? *)
- BEGIN
- fpart;
- IF Length(fstr) > 3 THEN result := 255;
- END;
- END
- ELSE result := 255;
- IF fname[nextch] = Chr(0) THEN nextch := 0;
- 999:
- END;
- (* ----------------------------------------------------------------------- *)
- (* Konvertierung des MS-DOS/TOS Datums in einen Date_Str: *)
- (* Datum - Bits: 0..4: Tag, 5..8: Monat, 9..15: Jahr-1980 *)
- PROCEDURE DOSDateStr (DOSDate: INTEGER; VAR Date: Date_Str);
- VAR temp: Dir_Str;
- BEGIN
- IntStr(ShiftR(DOSDate, 9) + 1980, 4, temp); (* Jahr *)
- Date := temp;
- IntStr(AndInt(ShiftR(DOSDate, 5), 15), 2, temp); (* Monat *)
- Date := Concat(Date, temp);
- IntStr(AndInt(DOSDate, 31), 2, temp); (* Tag *)
- Date := Concat(Date, temp);
- END;
-
- (* Konvertierung der MS-DOS/TOS Zeit in einen Time_Str: *)
- (* Zeit - Bits: *)
- (* 0..4: Sek. im 2-Sekunden-Intervall, 5..10: Minuten, 11..15: Stunden *)
- PROCEDURE DOSTimeStr (DOSTime: INTEGER; VAR Time: Time_Str);
- VAR temp: Dir_Str;
- BEGIN
- IntStr(ShiftR(DOSTime, 11), 2, temp); (* Stunden *)
- Time := temp;
- IntStr(AndInt(ShiftR(DOSTime, 5),63), 2, temp); (* Minuten *)
- Time := Concat(Time, temp);
- IntStr(AndInt(DOSTime, 31)*2, 2, temp); (* Sekunden *)
- Time := Concat(Time, temp);
- END;
- (* ----------------------------------------------------------------------- *)
- (* Dateigroesse eines mit FSFirst gefundenen Dateieintrages "errechnen": *)
- FUNCTION CompFSize: REAL;
- BEGIN
- WITH DirDTA^ DO CompFSize := IntCard(szhi) * 65536.0 + IntCard(szlo);
- END;
- (* ----------------------------------------------------------------------- *)
- (* Die TOS-"Pfad"-Funktionen mussten teilweise modifiziert werden, um ein *)
- (* gleiches Verhalten wie MS-DOS zu erlangen! *)
- (* aktuellen Pfad ermitteln: *)
- FUNCTION DGetPath (VAR path: Dir_Chr0; drive: INTEGER): INTEGER;
- VAR temp: Dir_Chr0; i: INTEGER;
- (* endgueltiger BS-Aufruf: *)
- FUNCTION DoDGetPath (VAR path: Dir_Chr0; drive: INTEGER): INTEGER;
- GEMDOS($47);
- BEGIN
- path[1] := Chr(0); (* fuer Fehlerfall *)
- i := DoDGetPath(temp,drive); (* BS-Funktion aufrufen *)
- DGetPath := i; (* und Fehlercode auswerten. *)
- IF i = DOSfnok THEN BEGIN
- (* falls Wurzelverzeichnis Backslash zurueck geben: *)
- IF temp[1] = Chr(0) THEN BEGIN temp[1] := '\'; temp[2] := Chr(0); END;
- i := 0; (* Ergebnis von DoDGetPath in path zurueckgeben: *)
- REPEAT i := Succ(i); path[i] := temp[i]; UNTIL temp[i] = Chr(0);
- END;
- END;
-
- FUNCTION DSetPath (VAR path: Dir_Chr0): INTEGER; (* neuen Pfad setzen *)
- VAR olddrv, err: INTEGER;
- (* endgueltiger BS-Aufruf: *)
- FUNCTION DoDSetPath (VAR pth: Dir_Chr0): INTEGER;
- GEMDOS($3B);
- BEGIN
- DSetPath := DOSpthnf; (* Pfad vorerst nicht gefunden *)
- IF path[1] <> Chr(0) THEN
- (* kein Laufwerk angegeben ? *)
- IF path[2] <> ':' THEN DSetPath := DoDSetPath(path) (* ja, ok *)
- ELSE IF path[3] <> Chr(0) THEN BEGIN
- olddrv := DGetDrive; (* sonst kurzzeitig das Laufwerk wechseln *)
- IF DSetDrive(Ord(UpCase(path[1]))-Ord('A')) = DOSfnok THEN BEGIN
- DSetPath := DoDSetPath(path); err := DSetDrive(olddrv);
- END;
- END;
- END;
-
- FUNCTION DCreate (VAR path: Dir_Chr0): INTEGER; (* neues Verzeichnis erz. *)
- GEMDOS($39);
-
- FUNCTION DDelete (VAR path: Dir_Chr0): INTEGER; (* Verzeichnis loeschen *)
- VAR temp: Dir_Chr0; i, j: INTEGER;
- (* endgueltiger BS-Aufruf: *)
- FUNCTION DoDDelete (VAR path: Dir_Chr0): INTEGER;
- GEMDOS($3A);
- BEGIN
- IF path[1] = Chr(0) THEN DDelete := DOSpthnf
- ELSE BEGIN
- i := 0; j := 0;
- IF path[1] = '\' THEN (* Pfad ab Wurzel angegeben ? *)
- (* ja, akt. Laufwerk davor setzen: *)
- BEGIN temp[1] := Chr(DGetDrive + Ord('A')); temp[2] := ':'; i := 2; END
- ELSE IF path[2] <> ':' THEN (* kein Laufwerk angegeben ? *)
- (* Referenz des aktuellen Verzeichnisses davor setzen: *)
- BEGIN temp[1] := '.'; temp[2] := '\'; i := 2; END;
- REPEAT i := Succ(i); j := Succ(j); temp[i] := path[j];
- UNTIL path[j] = Chr(0);
- DDelete := DoDDelete(temp);
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* freien Disk-Speicherplatz ermitteln: *)
- PROCEDURE DFree (VAR info: DSK_Info; drive: INTEGER);
- TYPE DInfo = ARRAY[1..4] OF LONG_INTEGER;
- VAR buf: DInfo;
- (* endgueltiger BS-Aufruf: *)
- PROCEDURE DoDFree (VAR buf: DInfo; drive: INTEGER);
- GEMDOS($36);
- BEGIN
- DirResult := DOSfnok;
- WITH info DO BEGIN
- IF drive <> 0 THEN
- IF AndInt(DrvMap,ShiftL(1,Pred(drive))) = 0 THEN BEGIN
- DirResult := DOSedriv; FreeCluster := -1.0; TotalCluster := -1.0;
- SectorSize := -1.0; ClusterSize := -1.0;
- END;
- IF DirResult = DOSfnok THEN BEGIN
- DoDFree(buf,drive);
- FreeCluster := buf[1]; TotalCluster := buf[2];
- SectorSize := buf[3]; ClusterSize := buf[4];
- END;
- END;
- END;
- (* ----------------------------------------------------------------------- *)
- (* DIRMT.PSP *)
-
-