{ -----------------------------------------------------------------------
Tcl Scripting Language Components (Tslc)
Copyright (C) 1996-2002 William Byrne

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

WilliamB@ByrneLitho.com
------------------------------------------------------------------------}
unit TslcIDE;

interface
uses Windows, Classes;

procedure Register;
function MacroAdd(key: Word; shift: TShiftState; caption, script: string): integer;
procedure MacroDelete(index: integer);
function MacroCount: integer;
function MacroKey(index: integer): Word;
function MacroCaption(index: integer): string;
function MacroScript(index: integer): string;
function MacroShift(index: integer): TShiftState;
function MacroShortCut(index: integer): integer;
function MacroShortCutStr(index: integer): string;
function MacroIndexOfShortCut(shortcut: integer): integer;
function MacroIndexOfCaption(caption: string): integer;
procedure MacroInvoke(index: integer);
function MacroFormSensitive(index: integer; value: boolean): boolean; // returns previous
procedure WarnActiveForm(value: boolean);
procedure FocusEditor;
function SwapActiveForm: boolean;
function DelphiHandle: integer;
procedure ProcessMessages;
function QueryInvocation: boolean;
procedure SaveAllUnits;

type
	TCloseProcedure = procedure;

procedure OnShutDown(proc: TCloseProcedure);

procedure OpenForm(formName: string; show: boolean);

implementation
uses SysUtils, Forms, Messages, ToolIntf, EditIntf, ExptIntf, libIntf,
{$IFDEF VER90}
 libmain,
{$ENDIF}
 uTslcIDE, TslcPlat, menus, Dialogs;

{$Z+}
{$D-,L-,Y-}


const
	cFormSensitive = 'Form Sensitive';

function MacroIndexOf(macro: Pointer): integer; forward;
function Macro(index: integer): TIMenuItemIntf; forward;

type

	TAddInNotifier = class(TIAddInNotifier)
  	public
    	procedure FileNotification(NotifyCode: TFileNotification;
      		const FileName: string; var Cancel: Boolean); override;
  	end;

	TMenuClickEvent = procedure (Sender: TIMenuItemIntf); stdcall;
	TTslcExpert = class(TIExpert)
    private
        FEditTslcScriptItem, FEditTslcPadItem: TIMenuItemIntf;
        FAddInNotifier: TAddInNotifier;
        FPrevAppMsg: TMessageEvent;
        function DoSwapActiveForm: integer;
        procedure MenuEvent(Sender: TIMenuItemIntf);

    public
        HotKeyList: TStringList;
		NameList: TStringList;
    	constructor Create;
        destructor Destroy; override;
        procedure ClosePad;
	    function GetName: string; override;
	    function GetAuthor: string; override;
    	function GetComment: string; override;
	    function GetPage: string; override;
    	function GetGlyph: HICON; override;
	    function GetStyle: TExpertStyle; override;
	    function GetState: TExpertState; override;
	    function GetIDString: string; override;
    	function GetMenuText: string; override;
	    procedure Execute; override;
        procedure MacroEvent(Sender: TIMenuItemIntf);
		function Release: longint; override;
    end;

var
	Expert: TTslcExpert;
    WarnActive: boolean = True;

procedure WarnActiveForm(value: boolean);
begin
	WarnActive := value;
end;

function SwapActiveForm: boolean;
begin
	case Expert.DoSwapActiveForm of
    	-1:
        	begin
            	result := False;
                exit;
            end;
        0:	CompLib.HideWindows;
    end;
	result := True;
end;

procedure SaveAllUnits;
begin
    ToolServices.SaveProject;
end;

procedure HandleException;
begin
{$IFDEF VER90}
	ToolServices.RaiseException(ReleaseException);
{$ELSE}
	ToolServices.RaiseException(Exception(ExceptObject).Message);
{$ENDIF}
end;

function IsAppBuilder(hwnd: HWND): boolean;
var
	buf: array[0..255] of char;
begin
	result := (hwnd <> 0) and IsWindow(hwnd) and (GetClassName(hwnd, buf, 255) > 0) and (strcomp(buf, 'TAppBuilder') = 0);
end;

function FindingHandle(hwnd: HWND; lparam: LPARAM): boolean; stdcall;
begin
	if IsAppBuilder(hwnd) then
    begin
    	pInteger(lparam)^ := hwnd;
        result := False;
    end else
    	result := True;
end;

function DelphiHandle: integer;
const
    hwnd: HWND = 0;
begin
	Result := hwnd;
    if not IsAppBuilder(Result) then
    begin
    	Result := 0;
		EnumThreadWindows(GetCurrentThreadId, @FindingHandle, longint(@Result));
		hwnd := Result;
	end;
end;

procedure ProcessMessages;
begin
	if Application <> nil then
    	Application.ProcessMessages;
end;

procedure TAddInNotifier.FileNotification(NotifyCode: TFileNotification;
      		const FileName: string; var Cancel: Boolean);
const
	cont: boolean = True;
    IDEScript: boolean = False;
var
    str, caption: string;
    buf: array[0..255] of char;
begin
//	str := inttostr(integer(NotifyCode)) + FileName;
//	MessageBox(0, pChar(str), 'Notify', 0);
	if not (NotifyCode in [fnProjectOpened]) then
    	exit;

	GetWindowText(DelphiHandle, buf, 255);
	try try
		if NotifyCode = fnProjectOpened then
        begin
        	if not IDEScript then
            begin
	        	SetWindowText(DelphiHandle, 'Running Initialization Script...');
            	IDEScript := True;
   	            EvalIDEScript;
            end;
			str := ChangeFileExt(FileName, '.tcl');
            if FileExists(str) then
            begin
                caption := Format('Running Project Script [%s]...', [str]);
				SetWindowText(DelphiHandle, pChar(caption));
	            EvalFile(str);
        	end;
		end else if NotifyCode = fnProjectClosing then
        begin


        end;
    finally
    	SetWindowText(DelphiHandle, buf);
    end;
	except
		MessageBox(0, pChar(Exception(ExceptObject).Message), 'Project Script Error', MB_OK);
    end;

{	if cont then
    	if Assigned(@FileName) then     WM_COMMAND Message
	    	cont := MessageBox(0, pChar(inttostr(integer(Addr(FileName)))), '', MB_OKCANCEL) = IDOK
        else cont := MessageBox(0, 'nil', '', MB_OKCANCEL) = IDOK;
}
end;

procedure MacroInvoke(index: integer);
var
	script: string;
    menu: TIMenuItemIntf;
begin
	menu := Macro(index);
    if menu = nil then
    	exit;

	with Expert.HotKeyList do
       	script := strings[index];

    if script = '' then
    	exit;

    if menu.GetHint = cFormSensitive then
   	case Expert.DoSwapActiveForm of
    	-1: exit;
    	0: CompLib.HideWindows;
	end;

    try try
    	uTslcIDE.EvalScript(script);
    finally
//		    	CompLib.ShowWindows;
	end;
    except
    	HandleException;
    end;

end;

procedure TTslcExpert.MacroEvent(Sender: TIMenuItemIntf);
begin
	MacroInvoke(MacroIndexOf(Sender));
end;

var
	F: TextFile;

var
	MenuCount: integer = 0;

procedure ListMenu(	MenuItems: TIMenuItemIntf; path: string );
var
	x: integer;
    mi : TIMenuItemIntf;
    info: string;
begin
	for x:= 0 to MenuItems.GetItemCount - 1 do
    begin
    	mi := MenuItems.GetItem(x);
        if mi <> nil then
	    try
        	Inc(MenuCount);
			info := Format('%s->%s, %s, %s, %d', [path, mi.GetCaption, mi.GetName,  ShortCutToText(mi.GetShortCut), mi.GetShortCut]);
			WriteLn(F, info);
			ListMenu(mi, Format('%s->%s',[path, mi.GetName]));
        finally
			mi.Free;
        end;
	end;
end;

procedure GetMenuList;
var
	MainMenu: TIMainMenuIntf;
    MenuItems: TIMenuItemIntf;
begin
	MainMenu := ToolServices.GetMainMenu;
	if MainMenu <> nil then
	try
    	MenuItems := MainMenu.GetMenuItems;
    	if MenuItems <> nil then
    	try
            AssignFile(F, 'menulist.txt');
            Rewrite(F);
            try
	            ListMenu(MenuItems, 'Main');
            finally
	            CloseFile(F);
            end;
    	finally
      		MenuItems.Free;
    	end;
  	finally
    	MainMenu.Free;
  	end;
end;


function EnumChildren(hwnd: HWND; lparam: LPARAM): boolean; stdcall;
const
	layer: integer = 0;
    doing: boolean = True;
var
	buf2, buf: array[0..255] of char;
	msg: TMsg;
begin
	inc(layer);
	GetWindowText(hwnd, buf, 255);
{    if lparam <> 0 then
    begin
	    strlcat(buf, '.', 255);
    	strlcat(buf, pChar(lparam),255);
    end;
}
//    strlcat(buf, pChar(inttostr(layer)), 255);
    result := True;
    if doing then
    begin
    	GetClassName(hwnd, buf2, 255);
        if strpas(buf2) = 'TEditControl' then
        begin
        	MessageBeep(0);
//        	PostMessage(hwnd, WM_SETFOCUS, 0, 0);
        end;
        if strpas(buf2) = 'TEditWindow' then
        begin
        	MessageBeep(0);
            MessageBeep(0);
        	PostMessage(hwnd, WM_SETFOCUS, 0, 0);
        end;

//        WriteLn(F, inttostr(layer) + 'Window Text: ' + strpas(buf));
//  		WriteLn(F, inttostr(layer) + ': ' + strpas(buf2));
        EnumChildWindows(hwnd, @EnumChildren, integer(@buf));
    end else
    case MessageDlg(buf, mtInformation, mbYesNoCancel, 0) of
    	IDYES:
        	begin
            	doing := True;
				GetClassName(hwnd, buf2, 255);
//				if strcomp(buf2, 'TEditControl') = 0 then
//                begin
//                	MessageBeep(0);
//					msg.Hwnd
//                	PostMessage(hwnd, WM_CHAR, word('^'), 0);
//                end;
//		        WriteLn(F, inttostr(layer) + 'Window Text: ' + strpas(buf));
//		  		WriteLn(F, inttostr(layer) + ': ' + strpas(buf2));
            	ShowMessage('Class: ' + strpas(buf2) );
	            EnumChildWindows(hwnd, @EnumChildren, integer(@buf));
                doing := False;
        	end;
        IDCANCEL: Result := False;
    end;
    dec(layer);
end;

function EnumThread(hwnd: HWND; lparam: LPARAM): boolean; stdcall;
var
	buf: array[0..255] of char;
begin
   	GetClassName(hwnd, buf, 255);
    if StrComp(buf, 'TEditWindow') = 0 then
    begin
	   	PostMessage(hwnd, WM_SETFOCUS, 0, 0);
        result := False;
    end else result := True;
end;

procedure FocusEditor;
begin
	EnumThreadWindows(GetCurrentThreadId, @EnumThread, 0);
end;

function TTslcExpert.DoSwapActiveForm: integer;
var
	form: TIForm;
begin
	result := 1;
  	if (Screen = nil) or (Screen.ActiveForm = nil) then
    	exit;
	form := CompLib.GetActiveForm;
{$IFDEF VER90}
    if form is TLibForm then
    with form as TLibForm do
        if (Designer <> nil) and (Designer.Form = Screen.ActiveForm) and (Module <> nil) then
        begin
        	if Module.FormIsTopmost then
            begin
            	if WarnActive then
                	case MessageDlg('Active form will be switched to DFM. Continue?' + #13 +
                    	'(this message can be deactivated by calling procedure WarnActive(False))', mtWarning,
                        mbYesNoCancel, 0) of
							idCancel:
    	                    	begin
                                	Show;
        	                    	result := -1;
            	                    exit;
                	            end;
                            idNo:
                                begin
                                	result := 0;
                                    exit;
                                end;
                    else
                    	Module.SwapSourceFormView;
                    end
                else
		        	Module.SwapSourceFormView
        	end;
        end else
            result := 0
    else
    	result := 0;
{$ELSE}
	if form <> nil then
    	form.Hide;
{$ENDIF}
end;

procedure TTslcExpert.MenuEvent(Sender: TIMenuItemIntf);
begin
//	AssignFile(F, 'Delme.txt');
//    Rewrite(F);
//	EnumThreadWindows(GetCurrentThreadId, @EnumChildren, 0);
//    CloseFile(F);
//    exit;
//	FocusEditor;
//    exit;
//	GetMenuList;
//    exit;
    try try
    	uTslcIDE.ExecuteScriptPad;
    finally
//    	CompLib.ShowWindows;
    end;
	except
    	HandleException;
    end;

end;

procedure TTslcExpert.Execute;
begin
end;

var
	CloseCallback: procedure = nil;

procedure OnShutDown(proc: TCloseProcedure);
begin
	CloseCallback := proc;
end;


procedure TTslcExpert.ClosePad;
begin
	try
    	if @CloseCallback <> nil then
        	CloseCallback;
    except
    end;
end;


function TTslcExpert.Release: Longint;
begin
	result := inherited Release;
    ClosePad;
end;


function TTslcExpert.GetName: string;
begin
	result := 'Tcl Script Pad';
end;

function TTslcExpert.GetAuthor: string;
begin
	result := 'William Byrne';
end;

function TTslcExpert.GetComment: string;
begin
	result := 'Tcl Scripting Language Component Script Pad';
end;

function TTslcExpert.GetPage: string;
begin
	result := '';
end;

function TTslcExpert.GetGlyph: HICON;
begin
	result := 0;
end;

function TTslcExpert.GetStyle: TExpertStyle;
begin
	result := esAddIn;
end;

function TTslcExpert.GetState: TExpertState;
begin
	result := [esEnabled];
end;

function TTslcExpert.GetIDString: string;
begin
	result := 'ByrneLitho.TslcScriptPad';
end;

function TTslcExpert.GetMenuText: string;
begin
	result := 'Script Pad...';
end;

type
	TMenuHack = class(TIMenuItemIntf)
    public
    	property OnClick: TIMenuClickEvent read GetOnClick;
	end;

constructor TTslcExpert.Create;
var
  	MainMenu: TIMainMenuIntf;
  	EditMenu: TIMenuItemIntf;
  	MenuItems: TIMenuItemIntf;
    key: word;
    shift: TShiftState;
    hotKey: integer;
    caption: string;
    ClickEvent: TIMenuClickEvent;
    p: pointer;
begin
	key := 0;
    shift := [];
    caption := '';
	if uTslcIDE.ScriptPadShortCut(caption, key, shift) then
    	hotKey := ShortCut(key, shift)
    else
    	hotKey := 0;
	inherited Create;

	MainMenu := ToolServices.GetMainMenu;
	if MainMenu <> nil then
	try
    	MenuItems := MainMenu.GetMenuItems;
    	if MenuItems <> nil then
    	try
    		EditMenu := MainMenu.FindMenuItem('EditMenu');
    		if EditMenu <> nil then
      		try
        		FEditTslcScriptItem := EditMenu.InsertItem(EditMenu.GetItemCount, caption, 'EditTslcScriptItem', '',
            		0, 0, 0,[mfVisible, mfEnabled], nil);
				if FEditTslcScriptItem <> nil then
                	FEditTslcPadItem := FEditTslcScriptItem.InsertItem(0, '&Pad...', 'EditTslcPadItem', '',
                        hotKey, 0, 0, [mfVisible, mfEnabled], MenuEvent);
            finally
        		EditMenu.Free;
        	end;
    	finally
      		MenuItems.Free;
    	end;
  	finally
    	MainMenu.Free;
  	end;
	FAddInNotifier := TAddInNotifier.Create;
	ToolServices.AddNotifier(FAddInNotifier);
    HotKeyList := TStringList.Create;
    NameList := TStringList.Create;
end;

destructor TTslcExpert.Destroy;
var
	x: integer;
begin
	ClosePad;
//	CompileItem.Free;
//    RunItem.Free;
//    BuildItem.Free;
	ToolServices.RemoveNotifier(FAddInNotifier);
  	FEditTslcScriptItem.Free;
	FAddInNotifier.Free;
//	for x := 0 to HotKeyList.Count - 1 do
//    	TIMenuItemIntf(HotKeyList.objects[x]).Free;
	HotKeyList.Free;
    NameList.Free;
  	inherited Destroy;
end;

function MacroAdd(key: Word; shift: TShiftState; caption, script: string): integer;
const
	hotKeyIter: integer = 0;
var
  	MainMenu: TIMainMenuIntf;
  	EditMenu, menu: TIMenuItemIntf;
  	MenuItems: TIMenuItemIntf;
    ident: string;
begin
	MacroDelete(MacroIndexOfShortCut(ShortCut(key, shift)));
	MainMenu := ToolServices.GetMainMenu;
	if MainMenu <> nil then
	try
    	MenuItems := MainMenu.GetMenuItems;
    	if MenuItems <> nil then
    	try
    		EditMenu := MainMenu.FindMenuItem('EditTslcScriptItem');
    		if EditMenu <> nil then
      		try
				inc(hotKeyIter);
            	ident := 'EditTslcPad' + inttostr(hotKeyIter) + 'Item';
        		menu := EditMenu.InsertItem(EditMenu.GetItemCount, caption, ident, '',
            		ShortCut(key, shift), 0, 0,[mfVisible, mfEnabled], Expert.MacroEvent);
                menu.SetHint(cFormSensitive);
				Expert.HotKeyList.addObject(script, menu);
            finally
        		EditMenu.Free;
        	end else
            	ShowMessage('No Tslc Script Menu Item');
    	finally
      		MenuItems.Free;
    	end else
        	ShowMessage('No Menu Items');
  	finally
    	MainMenu.Free;
  	end else
    	ShowMessage('No Main Menu');

    result := MacroIndexOf(menu);
end;

procedure MacroDelete(index: integer);
var
	menu: TIMenuItemIntf;
begin
	menu := Macro(index);
    if menu = nil then
    	exit;
	with Expert.HotKeyList do
	   	Delete(index);
    menu.Free;
end;

function MacroCount: integer;
begin
    result := Expert.HotKeyList.Count;
end;

function MacroKey(index: integer): Word;
var
	menu: TIMenuItemIntf;
    shift: TShiftState;
begin
	menu := Macro(index);
    result := 0;
    if menu = nil then
    	exit;
	ShortCutToKey(menu.GetShortCut, result, shift);
end;

function MacroFormSensitive(index: integer; value: boolean): boolean;
var
	menu: TIMenuItemIntf;
begin
	menu := Macro(index);
    if menu = nil then
    	result := False
    else
    begin
		result := menu.GetHint = cFormSensitive;
        if value then
        	menu.SetHint(cFormSensitive)
        else
        	menu.SetHint('');
	end;
end;

function MacroIndexOf(macro: Pointer): integer;
begin
	result := Expert.HotKeyList.IndexOfObject(TObject(macro));
end;

function MacroCaption(index: integer): string;
var
	menu: TIMenuItemIntf;
    key: word;
begin
	menu := Macro(index);
    result := '';
    if menu = nil then
    	exit;
	result := menu.GetCaption;
end;

function MacroScript(index: integer): string;
begin
	result := '';
    if Macro(index) = nil then
    	exit;
	with Expert.HotKeyList do
       	result := strings[index]
end;

function MacroShift(index: integer): TShiftState;
var
	menu: TIMenuItemIntf;
    key: word;
begin
	menu := Macro(index);
    if menu = nil then
    	result := []
    else
		ShortCutToKey(menu.GetShortCut, key, result);
end;

function MacroShortCutStr(index: integer): string;
var
	menu: TIMenuItemIntf;
begin
	menu := Macro(index);
    if menu = nil then
    	result := ''
    else
		result := ShortCutToText(menu.GetShortCut);
end;

function MacroShortCut(index: integer): integer;
var
	menu: TIMenuItemIntf;
begin
	menu := Macro(index);
    if menu = nil then
    	result := 0
    else
		result := menu.GetShortCut;
end;

function MacroIndexOfShortCut(shortcut: integer): integer;
var
	menu: TIMenuItemIntf;
    i: integer;
begin
	result := -1;
	for i := 0 to MacroCount - 1 do
    begin
		menu := Macro(i);
	    if menu = nil then
    		exit;
        if menu.GetShortCut = shortcut then
        begin
        	result := i;
            exit;
        end;
    end;
end;


function MacroIndexOfCaption(caption: string): integer;
var
	menu: TIMenuItemIntf;
    i, p: integer;
    cap: string;
begin
	result := -1;
	for i := 0 to MacroCount - 1 do
    begin
		menu := Macro(i);
	    if menu = nil then
    		exit;
        cap := menu.GetCaption;
        p := Pos('&', cap);
        if p > 0 then
        	Delete(cap, p, 1);
        if CompareText(cap, caption) = 0 then
        begin
        	result := i;
            exit;
        end;
    end;
end;


function Macro(index: integer): TIMenuItemIntf;
begin
	with Expert.HotKeyList do
    	if (index < count) and (index >= 0) then
        	result := TIMenuItemIntf(objects[index])
        else
        	result := nil;
end;

procedure OpenForm(formName: string; show: boolean);
begin
{$IFDEF VER90}
	AppBuilder.OpenForm(formName, show);
{$ENDIF}
end;

function FindingWindows(hwnd: HWND; lparam: LPARAM): boolean; stdcall;
var
	buf, buf2: array[0..255] of char;
    str: string;
begin
	GetClassName(hwnd, buf, 255);
    GetWindowText(hwnd, buf2, 255);
    result := not ((strpas(buf) = 'TForm') and (strpas(buf2) = ''));
    if not result then
    	ShowWindow(hwnd, SW_HIDE);
{	str := strpas(buf) + #13 + strpas(buf2);
    case  MessageBox(0, pChar(str), 'Which...', MB_YESNOCANCEL) of
    	IDYES:
        begin
        	ShowWindow(hwnd, SW_HIDE);
    		ShowMessage(inttostr(strlen(buf)) + ' ' + inttostr(strlen(buf2)));
	        result := True;
        end;
        IDCANCEL: result := False;
        IDNO : result := True;
    end;
 }
end;

//{$R RegDlg.res}
var              
	neverAgain: boolean;
	TaskWindows: pointer;

function QueryCB(hwndDlg: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): BOOL; stdcall;
var
	code, ctrl, id: integer;
    buf: array[0..255] of char;
    str: string;
    doEnd: boolean;
    pp: ^pointer;
begin
    if uMsg = WM_COMMAND then
    begin
		code := HIWORD(wParam);
        id := LOWORD(wParam);
        ctrl := lParam;
        if id in [ID_YES, ID_NO] then
        begin
           	doEnd := True;
	        if IsDlgButtonChecked(hwndDlg, 102) = 1 then
            begin
            	if id <> ID_YES then
                	doEnd := MessageBox(hwndDlg, 'Warning will remain in effect.', 'Information',
	                   	MB_ICONINFORMATION or MB_OKCANCEL) = ID_OK
                 else
                	neverAgain := True;
            end;
            if doEnd then
		    	EndDialog(hwndDlg, id);
        end;
    end else if uMsg = WM_INITDIALOG then
    begin
    	integer(pp) := lParam;
    	pp^ := DisableTaskWindows(hwndDlg);
    	SetFocus(GetDlgItem(hwndDlg, ID_NO));
    end;
	result := False;
end;

const
	cTslcRegWarn = 'DisableRegWarn';
    cTslcEvalWarn = 'DisableEvalWarn';
    cIDE = 'IDE';

function QueryRegister: boolean;
var
	i: integer;
    TaskWindows: pointer;
begin
	result := True;
	if TslcGetConfigInt(TslcGetUserName, cIDE, cTslcRegWarn, i) and (i <> 0) then
    	exit;

    neverAgain := False;
	TaskWindows := nil;
	try
		case DialogBoxParam(HINSTANCE, 'TSLC_IDE_REG_DLG', GetActiveWindow, @QueryCB, integer(@TaskWindows)) of
	    	-1: result := MessageBox(0, 'Install Tslc IDE?', 'Register Tslc IDE', MB_YESNO) = ID_YES;
	        ID_YES: result := True;
	    else
	    	result := False;
	    end;
		if neverAgain then
    		TslcSetConfigInt(TslcGetUserName, cIDE, cTslcRegWarn, 1);
    finally
    	EnableTaskWindows(TaskWindows);
    end;
end;

function QueryInvocation: boolean;
var
	i: integer;
    TaskWindows: pointer;
begin
	result := True;
    exit;
	if TslcGetConfigInt(TslcGetUserName, cIDE, cTslcEvalWarn, i) and (i <> 0) then
    	exit;

    neverAgain := False;
	TaskWindows := nil;
    try
		case DialogBoxParam(HINSTANCE, 'TSLC_IDE_EVAL_DLG', GetActiveWindow, @QueryCB, integer(@TaskWindows)) of
//    	-1: result := MessageBox(0, 'lc IDE?', 'Register Tslc IDE', MB_YESNO) = ID_YES;
	        ID_YES: result := True;
	    else
	    	result := False;
	    end;
	    if neverAgain then
	    	TslcSetConfigInt(TslcGetUserName, cIDE, cTslcEvalWarn, 1);
	finally
    	EnableTaskWindows(TaskWindows);
    end;
end;


procedure Register;
begin
	try
		EnumThreadWindows(GetCurrentThreadId, @FindingWindows, 0);
        if not QueryRegister then
        	exit;
	   	Expert := TTslcExpert.Create;
		RegisterLibraryExpert(Expert);
    except
    	MessageBox(0, pChar(Exception(ExceptObject).Message), 'TslcIDE Error', MB_SETFOREGROUND or MB_ICONSTOP or MB_TASKMODAL);
    end;
end;

end.


