MODULE DevComInterfaceGen;
(**

   project   = "BlackBox"
   organization   = "www.oberon.ch"
   contributors   = "Oberon microsystems"
   version   = "System/Rsrc/About"
   copyright   = "System/Rsrc/About"
   license   = "Docu/BB-License"
   changes   = ""
   issues   = ""

**)

   IMPORT COM, WinApi, WinOle, WinOleAut,

      Files, HostFiles, Strings, Dialog, StdDialog, Views, TextModels, TextViews, DevTypeLibs;
   TYPE

      Entry = POINTER TO RECORD   (* registry typelib entry *)
         next: Entry;
         index: INTEGER;
         guid: COM.GUID;
         major, minor: SHORTINT;
         lcid: WinApi.LCID;
         title: ARRAY 256 OF CHAR;
         file: ARRAY 256 OF CHAR
      END;
   VAR

      dialog*: RECORD
         library*: Dialog.List;
         fileName*: ARRAY 256 OF CHAR;
         modName*: ARRAY 64 OF CHAR;
         list, current: Entry
      END;
   PROCEDURE GetName (tlib: WinOleAut.ITypeLib; VAR name: ARRAY OF CHAR);

      VAR res: INTEGER; s: WinOle.BSTR;
   BEGIN
      res := tlib.GetDocumentation(-1, s, NIL, NIL, NIL);
      name := s$;
      IF (name[0] >= "a") & (name[0] <= "z") THEN name[0] := CAP(name[0]) END;
      name := "Ctl" + name;
      WinOleAut.SysFreeString(s)
   END GetName;
   PROCEDURE GenAutomationInterface*;

      VAR fn: Files.Name; loc: Files.Locator; t: TextModels.Model;
   BEGIN
      t := DevTypeLibs.AutomationInterface(dialog.fileName$, dialog.modName$);
      StdDialog.GetSubLoc(dialog.modName, "Mod", loc, fn); loc.res := 77;
      Views.Open(TextViews.dir.New(t), loc, fn, NIL)      
   END GenAutomationInterface;
   
   PROCEDURE GenCustomInterface*;
      VAR fn: Files.Name; loc: Files.Locator; t: TextModels.Model;
   BEGIN
      t := DevTypeLibs.CustomInterface(dialog.fileName$, dialog.modName$);
      StdDialog.GetSubLoc(dialog.modName, "Mod", loc, fn); loc.res := 77;
      Views.Open(TextViews.dir.New(t), loc, fn, NIL)      
   END GenCustomInterface;   
   
   PROCEDURE Browse*;
      VAR loc: Files.Locator; name: Files.Name;
         res: INTEGER; tlib: WinOleAut.ITypeLib; n: ARRAY 256 OF CHAR;   
   BEGIN
      Dialog.GetIntSpec("*", loc, name);
      IF loc # NIL THEN
         dialog.fileName := loc(HostFiles.Locator).path$ + "\" + name$;
         res := WinOleAut.LoadTypeLib(dialog.fileName, tlib);
         IF res >= 0 THEN
            GetName(tlib, n);
            dialog.modName := n$
         ELSE
            dialog.modName := ""
         END;         
         dialog.library.index := 0;
         Dialog.Update(dialog)
      END   
   END Browse;
   
   PROCEDURE TextFieldNotifier* (op, from, to: INTEGER);
      VAR res: INTEGER; tlib: WinOleAut.ITypeLib; n: ARRAY 256 OF CHAR;
   BEGIN
      res := WinOleAut.LoadTypeLib(dialog.fileName, tlib);
      IF res >= 0 THEN
         GetName(tlib, n);
         dialog.modName := n$
      ELSE
         dialog.modName := ""
      END;
      dialog.library.index := 0;
      Dialog.Update(dialog)      
   END TextFieldNotifier;
   PROCEDURE ListBoxNotifier* (op, from, to: INTEGER);

      VAR name: ARRAY 260 OF CHAR; res: INTEGER; e: Entry;
         tlib: WinOleAut.ITypeLib; n: ARRAY 256 OF CHAR;
   BEGIN
      IF op = Dialog.changed THEN
         IF dialog.library.index # dialog.current.index THEN
            e := dialog.list; WHILE e.index # dialog.library.index DO e := e.next END;
            dialog.current := e; dialog.fileName := e.file$
         END;
         res := WinOleAut.LoadTypeLib(dialog.fileName, tlib);
         IF res >= 0 THEN
            GetName(tlib, n);
            dialog.modName := n$
         ELSE
            dialog.modName := "";
            dialog.library.index := 0                     
         END;
         Dialog.Update(dialog)
      END
   END ListBoxNotifier;
   PROCEDURE InitDialog*;

      VAR tlKey, gKey, vKey, lidKey, fKey: WinApi.HKEY; guid: COM.GUID; e: Entry;
         i, j, k, res, idx, lcid, len: INTEGER; ver: REAL;
         wstr: ARRAY 256 OF CHAR; nstr: ARRAY 16 OF CHAR;
   BEGIN
      NEW(dialog.list); dialog.list.next := NIL;
      dialog.list.index := 0;
      dialog.list.title := " "; dialog.list.file := "";
      dialog.current := dialog.list;
      res := WinApi.RegOpenKeyW(WinApi.HKEY_CLASSES_ROOT, "TypeLib", tlKey);
      idx := 1;
      i := 0; res := WinApi.RegEnumKeyW(tlKey, i, wstr, LEN(wstr));
      WHILE res = 0 DO
         res := WinOle.CLSIDFromString(wstr, guid);
         IF res = 0 THEN
            res := WinApi.RegOpenKeyW(tlKey, wstr, gKey);
            j := 0; res := WinApi.RegEnumKeyW(gKey, j, wstr, LEN(wstr));
            WHILE res = 0 DO
               Strings.StringToReal(wstr, ver, res);
               IF res = 0 THEN
                  res := WinApi.RegOpenKeyW(gKey, wstr, vKey);
                  k := 0; res := WinApi.RegEnumKeyW(vKey, k, wstr, LEN(wstr));
                  WHILE res= 0 DO
                     Strings.StringToInt(wstr, lcid, res);
                     IF res = 0 THEN
                        res := WinApi.RegOpenKeyW(vKey, wstr, lidKey);
                        res := WinApi.RegOpenKeyW(lidKey, "Win32", fKey);
                        IF res # 0 THEN res := WinApi.RegOpenKeyW(lidKey, "Win16", fKey) END;
                        IF res = 0 THEN
                           NEW(e); e.next := dialog.list; dialog.list := e;
                           e.index := idx; INC(idx);
                           e.guid := guid;
                           e.major := SHORT(SHORT(ENTIER(ver)));
                           e.minor := SHORT(SHORT(ENTIER(ver * 100)) MOD 100);
                           e.lcid := lcid;
                           len := LEN(e.title);
                           res := WinApi.RegQueryValueW(vKey, NIL, e.title, len);
                           Strings.RealToString(ver, wstr);
                           Strings.IntToString(lcid, nstr);
                           e.title := e.title + " (" + wstr + ", " + nstr + ")";
                           len := LEN(e.file);
                           res := WinApi.RegQueryValueW(fKey, NIL, e.file, len)
                        END
                     END;
                     INC(k); res := WinApi.RegEnumKeyW(vKey, k, wstr, LEN(wstr))
                  END
               END;
               INC(j); res := WinApi.RegEnumKeyW(gKey, j, wstr, LEN(wstr))
            END
         END;
         INC(i); res := WinApi.RegEnumKeyW(tlKey, i, wstr, LEN(wstr))
      END;
      dialog.library.SetLen(idx); e := dialog.list;
      WHILE e # NIL DO dialog.library.SetItem(e.index, e.title); e := e.next END;
      IF dialog.list.next # NIL THEN dialog.library.index := 1 ELSE dialog.library.index := 0 END;
      ListBoxNotifier(Dialog.changed, 0, 0)
   END InitDialog;
      
END DevComInterfaceGen.
"DevComInterfaceGen.InitDialog; StdCmds.OpenToolDialog('Dev/Rsrc/ComInterfaceGen', 'Generate Automation Interface')"