(*---------------------------------------------------------------------------
    :Program.    CreateIcons.mod
    :Author.     Fridtjof Siebert
    :Address.    Nobileweg 67, D-7000-Stgt-40
    :Phone.      0711/822509
    :Shortcut.   [fbs]
    :History.    V0.8, 06-Aug-88 [fbs]: CreateAmokDisk in M2
    :History.    V1.0, 19-Nov-89 [fbs]: ported to OBERON
    :Copyright.  PD
    :Language.   OBERON
    :Translator. AMOK OBERON Compiler V0.1.1
    :Imports.    SecureDos [fbs]
    :Imports.    Lists [fbs]
    :Contents.   Icon creation tool. Kopiert die Icons aus ICONS: mit dem
    :Contents.   xxx.info zu den Dateien abc.xxx.
    :Usage.      CreateIcons <Disk or Directory>
---------------------------------------------------------------------------*)

DEFINITION CreateIcons; END CreateIcons.

IMPLEMENTATION CreateIcons;

IMPORT d:   Dos,
            io,
            Break,
            NoGuru,
       sd:  SecureDos,
       li:  Lists,
       arg: Arguments,
       str: Strings,
       ol:  OberonLib;


TYPE String = ARRAY 80 OF CHAR;

VAR
  Name: String;
  LockPtr: d.FileLockPtr;
  oldCD: d.FileLockPtr;


PROCEDURE PutIcon(Iconname: ARRAY OF CHAR; to: ARRAY OF CHAR);
(* Kopiert das Icon "ICONS:"+Iconname+".info" nach to *)

VAR
  i,o: ARRAY 80 OF CHAR;
  in,out: d.FileHandlePtr;
  size: LONGINT;
  buf: LONGINT;
  CD: d.FileLockPtr;

BEGIN
  o := ""; str.Append(o,to); str.Append(o,".info");

  in := sd.Open(ADR(o),d.oldFile);         (* exisitiert Icon schon? *)
  IF in#NIL THEN sd.Close(in); RETURN END; (* Ja, dann zurück        *)

  CD := d.CurrentDir(oldCD);               (* Icon lesen:            *)
  i := "ICONS/"; str.Append(i,Iconname); str.Append(i,".info");
  in := sd.Open(ADR(i),d.oldFile);
  CD := d.CurrentDir(CD);
  IF in=NIL THEN
    i := "ICONS:"; str.Append(i,Iconname); str.Append(i,".info");
    in := sd.Open(ADR(i),d.oldFile);
    IF in=NIL THEN RETURN END;
  END;
  size := d.Seek(in,0,d.end);
  size := d.Seek(in,0,d.beginning);
  IF size<=0 THEN RETURN END;
  ol.New(buf,size); IF buf=NIL THEN RETURN END;
  IF d.Read(in,buf,size)#size THEN RETURN END;
  sd.Close(in);

  out := sd.Open(ADR(o),d.newFile);        (* Icon erzeugen          *)
  IF out=NIL THEN RETURN END;
  IF d.Write(out,buf,size)#0 THEN END;
  sd.Close(out);
  DISPOSE(buf);

END PutIcon;


(*--------------------  Rekursive Hauptprozedur:  -------------------------*)


PROCEDURE DoIt(lock: d.FileLockPtr; Depth: INTEGER);

TYPE
  NameTypePtr = POINTER TO NameType;
  NameType = RECORD (li.Node) name: String END;

VAR
  FileInfo: d.FileInfoBlockPtr;
  Err: LONGINT;
  Lock2, old, exists: d.FileLockPtr;
  FirstName, ActName: NameTypePtr;
  node: li.NodePtr;
  IconName: String;
  pos: INTEGER;


  PROCEDURE Tab;
  VAR i: INTEGER;
  BEGIN
    i:=0; WHILE i<=Depth DO io.WriteString("  "); INC(i) END;
  END Tab;


  PROCEDURE oom;
  BEGIN
    io.WriteString("Out of memory!\n"); HALT(0);
  END oom;


BEGIN

(*------  Init:  ------*)

  FirstName := NIL;

  NEW(FileInfo);
  IF FileInfo=NIL THEN oom END;

  old := d.CurrentDir(lock);

  IF d.Examine(lock,FileInfo) THEN
    WHILE d.ExNext(lock,FileInfo) DO
      IF FileInfo.dirEntryType>0 THEN   (* directory: *)

        str.Cut(FileInfo.fileName,0,SIZE(IconName),IconName);
        PutIcon("dir",FileInfo.fileName);
        Tab; io.WriteString(FileInfo.fileName);
        io.WriteString("  (Directory)\n");
        Lock2 := sd.Lock(ADR(FileInfo^.fileName),d.sharedLock);
        IF Lock2#NIL THEN DoIt(Lock2,Depth+1) END;
        sd.UnLock(Lock2);

      ELSE                               (* file: *)

        IF str.Occurs(FileInfo.fileName,".info")=-1 THEN
          NEW(ActName);
          IF ActName=NIL THEN oom END;
          str.Cut(FileInfo.fileName,0,SIZE(ActName.name),ActName.name);
          li.Add(FirstName,ActName^);
        END;

      END;
    END;
  END;

  Err := d.IoErr();
  IF (Err#d.noMoreEntries) THEN
    Tab; io.WriteString("IO-Error: "); io.WriteInt(Err,6); io.WriteLn; HALT(0);
  END;

  node := FirstName;         (* Icons erzeugen: *)
  WHILE node#NIL DO
    WITH node : NameType DO
      Tab(); io.WriteString(node.name); io.WriteLn;
      pos := str.Occurs(node.name,".");
      IF pos=-1 THEN
        IconName := "bin"
      ELSE
        str.Cut(node.name,pos+1,str.Length(node.name)-pos-1,IconName)
      END;
      PutIcon(IconName,node.name);
    END;
    node := node.next;
  END;

  old := d.CurrentDir(old);   (* zurück zum alten Directory *)

  DISPOSE(FileInfo);          (* Speicher freigeben: *)
  WHILE FirstName#NIL DO
    ActName := FirstName;
    li.Rem(FirstName,ActName^);
    DISPOSE(ActName);
  END;

END DoIt;


BEGIN

  oldCD := ol.Me.currentDir;

  io.WriteString("Amok -- Icon creation tool. 1988 by Fridtjof Siebert\n");

  IF arg.NumArgs()#1 THEN
    io.WriteString("Usage: CreateIcons <Name>\n"); HALT(0)
  END;
  arg.GetArg(1,Name);

  LockPtr := sd.Lock(ADR(Name),d.sharedLock);

  IF LockPtr=NIL THEN
    io.WriteString("IO-Error: "); io.WriteInt(d.IoErr(),6); io.WriteLn;
    HALT(0);
  END;

  IF (Name#"") AND (Name[str.Length(Name)-1]=":") THEN   (* Diskicon *)
    str.Append(Name,"disk");
    PutIcon("disk",Name);
  END;

  DoIt(LockPtr,0);
  sd.UnLock(LockPtr);

END CreateIcons.
