MODULE DLdrives;

IMPORT
  d   := Dos,
  e   := Exec,
  DLp := DLprefs,
  DLr := DLrequester,
  DLs := DLstrings,
  gt  := GadTools,
  I   := Intuition,
  pf  := Printf,
  sd  := SecureDos,
  sys := SYSTEM,
  u   := Utility;

CONST
  maxTitles -= 20;

TYPE
  DoProc = PROCEDURE(VAR t: DLp.driveT);

VAR
  mywin        *: I.WindowPtr;
  winactive    *: BOOLEAN;
  count 	: INTEGER;
  title 	: ARRAY maxTitles+1 OF CHAR;
  info		: d.InfoData;
  outfhp	: d.FileHandlePtr;
  infhp 	: d.FileHandlePtr;

(*------ Repeat »what« for every drive in »with« --------------------------*)

PROCEDURE DoIt(VAR with: DLp.driveP; what: DoProc);
BEGIN
  FOR count := 1 TO DLp.Prefs.DriveNum DO
    what(with[count-1]);
  END;
END DoIt;

(*------ Check whether drive locked or disabled ---------------------------*)

PROCEDURE * CheckD(VAR n: DLp.driveT);
VAR olddisabled : BOOLEAN;
    lockPtr	: d.FileLockPtr;
BEGIN
  olddisabled := n.disabled;
  lockPtr := sd.Lock(n.DeviceName,d.accessRead);
  IF lockPtr # NIL THEN
    IF (d.Info(lockPtr,info) & (info.diskState # d.validating)) THEN
      n.locked :=  info.diskState = d.writeProtect;
      n.disabled := FALSE;
    ELSE
      n.disabled := TRUE;
    END;
    sd.UnLock(lockPtr);
  ELSE
    n.disabled := TRUE;
  END;
  IF n.disabled THEN n.locked := FALSE END;
  n.disabledchanged := n.disabledchanged OR (olddisabled # n.disabled);
END CheckD;

(*----- Lock n.DeviceName -----------------------------------------------------*)

PROCEDURE * LckOne*(VAR n: DLp.driveT);
VAR result : LONGINT;
BEGIN
  CheckD(n);
  IF n.disabled OR n.locked THEN
    RETURN;
  END;
  pf.SPrintf2(DLp.Buffer1,DLp.Prefs.LockString,sys.ADR(n.DeviceName),sys.ADR(n.PassKey));
  result := d.SystemTags(DLp.Buffer1,d.sysOutput,sys.VAL(e.ADDRESS,outfhp),
				     d.sysInput,sys.VAL(e.ADDRESS,infhp),u.done);
  IF result < 0 THEN DLr.BailOut(DLs.GetString(DLs.ErrCantExLock)^) END;
  IF result > 0 THEN
    DLr.RequestNotify(DLs.GetString(DLs.MsgProblem),DLs.GetString(DLs.ProbCantLock),sys.ADR(n.PrintName));
  END;
END LckOne;

PROCEDURE * LckOneMini(VAR n: DLp.driveT);
VAR result : LONGINT;
BEGIN
  pf.SPrintf2(DLp.Buffer1,DLp.Prefs.LockString,sys.ADR(n.DeviceName),sys.ADR(n.PassKey));
  result := d.SystemTags(DLp.Buffer1,d.sysOutput,sys.VAL(e.ADDRESS,outfhp),
				     d.sysInput,sys.VAL(e.ADDRESS,infhp),u.done);
END LckOneMini;

(*------ UnLock n.DeviceName --------------------------------------------------*)

PROCEDURE * UnLckOne*(VAR n: DLp.driveT);
VAR result : LONGINT;
BEGIN
  CheckD(n);
  IF n.disabled OR ~n.locked THEN
    RETURN;
  END;
  pf.SPrintf2(DLp.Buffer1,DLp.Prefs.UnlockString,sys.ADR(n.DeviceName),sys.ADR(n.PassKey));
  result := d.SystemTags(DLp.Buffer1,d.sysOutput,sys.VAL(e.ADDRESS,outfhp),
				d.sysInput,sys.VAL(e.ADDRESS,infhp),u.done);
  IF result < 0 THEN DLr.BailOut(DLs.GetString(DLs.ErrCantExUnlock)^) END;
  IF result > 0 THEN
    DLr.RequestNotify(DLs.GetString(DLs.MsgProblem),DLs.GetString(DLs.ProbCantUnlock),sys.ADR(n.PrintName));
  END;
END UnLckOne;

PROCEDURE * UnLckOneMini(VAR n: DLp.driveT);
VAR result : LONGINT;
BEGIN
  pf.SPrintf2(DLp.Buffer1,DLp.Prefs.UnlockString,sys.ADR(n.DeviceName),sys.ADR(n.PassKey));
  result := d.SystemTags(DLp.Buffer1,d.sysOutput,sys.VAL(e.ADDRESS,outfhp),
				d.sysInput,sys.VAL(e.ADDRESS,infhp),u.done);
END UnLckOneMini;

(*------ Set Gadgets dependend of n.locked and n.disabled -----------------*)

PROCEDURE * Refresh(VAR n: DLp.driveT);
BEGIN
  IF n.disabledchanged THEN 
    gt.SetGadgetAttrs(n.GadPtr^,mywin,NIL,I.gaDisabled,sys.VAL(SHORTINT,n.disabled),u.done);
    IF (count <= maxTitles) THEN title[count-1] := "·" END;
  END;
  IF n.disabled THEN
    IF n.disabledchanged THEN 
      gt.SetGadgetAttrs(n.GadPtr^,mywin,NIL,gt.cbChecked,I.LFALSE,u.done);
    END;
  ELSE
    IF n.locked THEN
      gt.SetGadgetAttrs(n.GadPtr^,mywin,NIL,gt.cbChecked,I.LTRUE,u.done);
      IF (count <= maxTitles) THEN title[count-1] := "-" END;
    ELSE
      gt.SetGadgetAttrs(n.GadPtr^,mywin,NIL,gt.cbChecked,I.LFALSE,u.done);
      IF (count <= maxTitles) THEN title[count-1] := "+" END;
    END;
  END;
  I.SetWindowTitles(mywin,sys.ADR(title),-1);
  n.disabledchanged := FALSE;
END Refresh;

(*------ Auto-Lock procedures ---------------------------------------------*)

PROCEDURE * LockInit(VAR n: DLp.driveT);
BEGIN
  IF n.lockprefs = DLp.LPlock THEN LckOneMini(n)
  ELSIF n.lockprefs = DLp.LPunlock THEN UnLckOneMini(n)
  END;
END LockInit;

PROCEDURE * LockIfNecessary(VAR n: DLp.driveT);
BEGIN
  IF n.disabledchanged THEN
    IF (n.lockprefs = DLp.LPlock) & ~ n.disabled THEN
      LckOneMini(n);
      CheckD(n);
    END;
  END;
END LockIfNecessary;

(*------ Check drives -----------------------------------------------------*)

PROCEDURE CheckDrivesInit*();
BEGIN
  DoIt(DLp.drive,CheckD);
  DoIt(DLp.drive,LockInit);
END CheckDrivesInit;

PROCEDURE CheckDrives*(force: BOOLEAN);
BEGIN
  DoIt(DLp.drive,CheckD);
  DoIt(DLp.drive,LockIfNecessary);
  IF (mywin # NIL) & ((~ winactive) OR force)
  THEN DoIt(DLp.drive,Refresh)
  END;
END CheckDrives;

PROCEDURE OneLocked*():BOOLEAN;
BEGIN
  FOR count := 1 TO DLp.Prefs.DriveNum DO
    IF DLp.drive[count-1].locked THEN RETURN (TRUE) END;
  END;
  RETURN (FALSE);
END OneLocked;

(*------ (Un)Lock all drives ----------------------------------------------*)

PROCEDURE UnlockAll*(mini: BOOLEAN);
BEGIN
  IF mini THEN
    DoIt(DLp.drive,UnLckOneMini)
  ELSE
    DoIt(DLp.drive,UnLckOne)
  END;
END UnlockAll;

PROCEDURE LockAll*(mini: BOOLEAN);
BEGIN
  IF mini THEN
    DoIt(DLp.drive,LckOneMini)
  ELSE
    DoIt(DLp.drive,LckOne)
  END;
END LockAll;

PROCEDURE NormAll*();
BEGIN
  FOR count := 0 TO DLp.Prefs.DriveNum-1 DO
    IF DLp.drive[count].lockprefs = DLp.LPlock THEN
      LckOne(DLp.drive[count])
    ELSIF DLp.drive[count].lockprefs = DLp.LPunlock THEN
      UnLckOne(DLp.drive[count])
    END;
  END;
END NormAll;

(***************************************************************************
	 M A I N
 ***************************************************************************)

BEGIN

  outfhp := sd.Open("NIL:",d.readWrite);
  IF outfhp = NIL THEN DLr.FailOut("Open(out)") END;
  infhp := sd.Open("NIL:",d.readWrite);
  IF infhp = NIL THEN DLr.FailOut("Open(in)") END;

(***************************************************************************
	 C L O S E
 ***************************************************************************)

CLOSE
    IF infhp  # NIL THEN sd.Close(infhp)  END;
    IF outfhp # NIL THEN sd.Close(outfhp) END;


END DLdrives.
