Dev/Mod/ComInterfaceGen.odc

MODULE DevComInterfaceGen;
(**
	project	= "BlackBox"
	organization	= "www.oberon.ch"
	contributors	= "Oberon microsystems"
	version	= "System/Rsrc/About"
	copyright	= "System/Rsrc/About"
	license	= "Docu/BB-License"
	changes	= "
	- YYYYMMDD, nn, ...
	"
	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;
			name: ARRAY 256 OF SHORTCHAR; 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.RegOpenKey(WinApi.HKEY_CLASSES_ROOT, "TypeLib", tlKey);
		idx := 1;
		i := 0; res := WinApi.RegEnumKey(tlKey, i, name, LEN(name)); wstr := name$;
		WHILE res = 0 DO
			res := WinOle.CLSIDFromString(wstr, guid);
			IF res = 0 THEN
				res := WinApi.RegOpenKey(tlKey, name, gKey);
				j := 0; res := WinApi.RegEnumKey(gKey, j, name, LEN(name)); wstr := name$;
				WHILE res = 0 DO
					Strings.StringToReal(wstr, ver, res);
					IF res = 0 THEN
						res := WinApi.RegOpenKey(gKey, name, vKey);
						k := 0; res := WinApi.RegEnumKey(vKey, k, name, LEN(name)); wstr := name$;
						WHILE res  = 0 DO
							Strings.StringToInt(wstr, lcid, res);
							IF res = 0 THEN
								res := WinApi.RegOpenKey(vKey, name, lidKey);
								res := WinApi.RegOpenKey(lidKey, "Win32", fKey);
								IF res # 0 THEN res := WinApi.RegOpenKey(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.RegQueryValue(vKey, NIL, name, len); e.title := name$;
									Strings.RealToString(ver, wstr);
									Strings.IntToString(lcid, nstr);
									e.title := e.title + " (" + wstr + ", " + nstr + ")";
									len := LEN(e.file);
									res := WinApi.RegQueryValue(fKey, NIL, name, len); e.file := name$
								END
							END;
							INC(k); res := WinApi.RegEnumKey(vKey, k, name, LEN(name)); wstr := name$
						END
					END;
					INC(j); res := WinApi.RegEnumKey(gKey, j, name, LEN(name)); wstr := name$
				END
			END;
			INC(i); res := WinApi.RegEnumKey(tlKey, i, name, LEN(name)); wstr := name$
		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')"