/******************************************************************************
 *
 * Copyright (c) 1999	TOSHIYUKI ARAI. ALL RIGHTS RESERVED. 
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer.
 *  
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *	RegistryViewer.cpp
 *
 *****************************************************************************/

// SOL++2000
// 2000.02.18


#include <sol\ApplicationView.h>
#include <shellapi.h>
#include <sol\TreeView.h>

#include "resource.h"


class RegistryTree :public TreeView {

public:
	RegistryTree() :TreeView() { }
	RegistryTree(View* parent, const char* name, Args& args)
		:TreeView(parent, name, args) { }
	virtual Boolean create(View* parent, const char* name, Args& args) {
		return TreeView::create(parent, name, args);
	}

	void build(HTREEITEM parent, HKEY hkey, LPCSTR subkey, int level);

};


// Build a registry tree structure
void RegistryTree::build(HTREEITEM parent, HKEY hkey, LPCSTR subkeyName, int n)
{
	HKEY hsubkey;
	HTREEITEM item = (HTREEITEM)TVI_FIRST;
	
	if (::RegOpenKey(hkey, subkeyName, &hsubkey) == ERROR_SUCCESS) {
		char buff[256];
		int indx = 0;
		while(::RegEnumKey(hsubkey, indx, buff, sizeof(buff)) == ERROR_SUCCESS) {
			indx++;
			if(*buff == '.') {
				continue;
			}		
			item = addItem(parent, item, buff); 

			build(item, hsubkey, buff, n+1);
    	}
		::RegCloseKey(hsubkey);
	}

}


class RegistryViewer :public ApplicationView {
	RegistryTree	treev;
	void	listUp(Action& action);

  public:
  	RegistryViewer(Application& applet, const char* name, Args& args);
};



RegistryViewer::RegistryViewer(Application& applet, const char* name, Args& args)
	:ApplicationView(applet, name, args)
{
	Args ar;
	ar.set(XmNexStyle, (ulong)WS_EX_CLIENTEDGE);
	ar.set(XmNstyle, (ulong)TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT);
	treev.create(this, "", ar);

	add(treev);

	addCallback(XmNmenuCallback, ID_CLASSES_ROOT, this,
		(Callback)&RegistryViewer::listUp, NULL);
	addCallback(XmNmenuCallback, ID_CURRENT_USER, this,
		(Callback)&RegistryViewer::listUp, NULL);
	addCallback(XmNmenuCallback, ID_LOCAL_MACHINE, this,
		(Callback)&RegistryViewer::listUp, NULL);
	addCallback(XmNmenuCallback, ID_USERS, this,
		(Callback)&RegistryViewer::listUp, NULL);
	addCallback(XmNmenuCallback, ID_CURRENT_CONFIG, this,
		(Callback)&RegistryViewer::listUp, NULL);
	addCallback(XmNmenuCallback, ID_DYN_DATA, this,
		(Callback)&RegistryViewer::listUp, NULL);

	addCallback(XmNmenuCallback, ID_EXIT, this,
		(Callback)&RegistryViewer::exit, NULL);
}


void	RegistryViewer::listUp(Action& action)
{
	HKEY hkey;
	Event& event = action.getEvent();
	int menuID = event.getMenuId();

	treev.deleteAllItems();

	HKEY regkey = null;
	if (menuID == ID_CLASSES_ROOT)   regkey = HKEY_CLASSES_ROOT;
	if (menuID == ID_CURRENT_USER)   regkey = HKEY_CURRENT_USER;
	if (menuID == ID_LOCAL_MACHINE)  regkey = HKEY_LOCAL_MACHINE;
	if (menuID == ID_USERS)          regkey = HKEY_USERS;
	if (menuID == ID_CURRENT_CONFIG) regkey = HKEY_CURRENT_CONFIG;
	if (menuID == ID_DYN_DATA)       regkey = HKEY_DYN_DATA;

	if (::RegOpenKey(regkey, NULL, &hkey) == ERROR_SUCCESS) {
		char top[10];
		strcpy(top, "Registry");
		HTREEITEM root = treev.addItem(NULL, TVI_ROOT, top);

		treev.build(root, hkey, NULL, 0);
		treev.sortChildren(root, TRUE);
		treev.expand(root, TVE_EXPAND);

		::RegCloseKey(hkey);
	}		
}



void Main(int argc, char** argv)
{
	const char* name = "RegistryViewer";
	Application applet(name, argc, argv);
	Args args;
	RegistryViewer viewer(applet, name, args);
	viewer.realize();
	applet.run();
}

