/******************************************************************************
 *
 * 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.
 *
 *
 *	SolFinger.cpp
 *
 *****************************************************************************/

// SOL++2000
// 2000.02.18


#include <sol\ApplicationView.h>
#include <sol\PushButton.h>
#include <sol\LabelGadget.h>
#include <sol\TextField.h>
#include <sol\Profile.h>
#include <sol\ScrolledRichText.h>
#include <sol\SocketStream.h>
#include <sol\Font.h>
#include <sol\ClientDC.h>
#include <sol\PaintDC.h>
#include <sol\stdio.h>
#include <sol\InetAddress.h>
#include <sol\Exception.h>
#include <sol\SocketSelector.h>

#include "resource.h"



class SolFinger :public ApplicationView {
	int					textHeight;
	LabelGadget			hostName;
	LabelGadget			userName;
	TextField			hostField;
	TextField			userField;
	PushButton			query;
	Font				font;
	SocketStream*		sock;
	ScrolledRichText	sctext;

	void	clear(Action& action);
	long	size(Event& event);
	long	close(Event& event);
	long	paint(Event& event);
	void	recv();
	void	doQuery(Action& action);

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


SolFinger::SolFinger(Application& applet, const char* name, Args& args)
	:ApplicationView(applet, name, args)
{
	sock = NULL;

	int cx = ::GetSystemMetrics(SM_CXSCREEN);
	int fheight = -12;
	if(cx > 1024) {
		fheight = -14;
	}
	Args ar;
	ar.set(XmNheight, fheight);
	font.create(ar);

	ClientDC dc(this);
	HFONT prevFont = (HFONT)dc.select(&font);
	textHeight = dc.getTextHeight();
	dc.select(prevFont);

	ar.reset();
	sctext.create(this, "", ar);
	sctext.setFont(font);
	
	sctext.limitText(20000);
	sctext.setReadOnly();

	sctext.addCallback(XmNmaxTextCallback, this, (Callback)&SolFinger::clear, NULL);

	ar.reset();
	hostName.create(this, "Host", ar);
	hostName.setFont(font);

	ar.reset();
	userName.create(this, "User", ar);
	userName.setFont(font);

	ar.reset();
	hostField.create(this, "",   ar);
	hostField.setFont(font);
	hostField.limitText(255);
	ar.reset();
	userField.create(this, "",   ar);
	userField.setFont(font);
	userField.limitText(255);

	ar.reset();
	query.create(this, "Query",   ar);
	query.setFont(font);
	query.addCallback(XmNactivateCallback, this, (Callback)&SolFinger::doQuery, NULL);

	addCallback(XmNmenuCallback, IDM_CLEAR, this, (Callback)&SolFinger::clear, NULL);
	addCallback(XmNmenuCallback, IDM_EXIT, this, (Callback)&SolFinger::exit, NULL);

	addEventHandler(WM_CLOSE, this, (Handler)&SolFinger::close, NULL);
	addEventHandler(WM_PAINT, this, (Handler)&SolFinger::paint, NULL);

	restorePlacement("SOLFINGER");
}


SolFinger::~SolFinger() 
{
	delete sock;
}


void SolFinger::clear(Action& action) 
{ 
	hostField.clear();
	userField.clear();
	sctext.clear(); 
}


long SolFinger::close(Event& event)
{
	savePlacement("SOLFINGER");				
	return defaultProc(event);
}


void SolFinger::recv()
{			
	sctext.clear();
	int bytes = 0;
	char buffer[256];

	if(!sock) {
		return;
	}

	while(1) {
		bytes = sock ->recv(buffer, sizeof(buffer)-1, 0);
		if(bytes <= 0) {
			break;
		}	
		buffer[bytes] = Zero;
		sctext.append(buffer);
	}
}



void SolFinger::doQuery(Action& action)
{
	char host[256];
	host[0] = Zero;
	hostField .getText(host, sizeof(host));
	char user[256];
	user[0] = Zero;
	userField.getText(user, sizeof(user));
	if(strlen(host) == 0 && strlen(user) == 0) {
		return;
	}

	sock = new SocketStream(AF_INET, 0);
	
	// Support a simple query command for finger.
	try {
		InetAddress address(host, IPPORT_FINGER);

		int rc = sock -> connect(address);
		StringBuffer sb;
		// Set a verbose mode.
		const char* verbose = "/W ";
		if (strstr(user, verbose) == null) {
			sb.append(verbose);
		}
		// Send a user-name with "\r\n".
		sb.append(user);
		sb.append("\r\n");
		sock -> sendAll(sb);

		// Read a reply from server.
		recv();

	} catch (Exception& ex) {
		ex.print();
		sctext.clear();
		showMessageDialog("Error", ex.getString());
	}
	sock -> shutdown(2);
	delete sock;
	sock = NULL;
}


long SolFinger::paint(Event& event) 
{
	PaintDC dc(this);
	hostName.draw(&dc);
	userName.draw(&dc);

	return 0L;
}


long SolFinger::size(Event& event)
{
	LPARAM pos = event.getLParam();
	int h = HIWORD(pos);
	int w = LOWORD(pos);
	int y =  textHeight+8;
	int lw = textHeight*2;
	int top = 4;
	int m   = 4;
	int ww, hh;
	query.getSize(ww, hh);

	hostName .setLocation(m, top);
	hostField.reshape(m*2+lw, top, w-m*2-lw-ww-m, y);
	userName .setLocation(m, top+y+10);
	userField.reshape(m*2+lw, top+y+10, w-m*2-lw-ww-m, y);
	query    .reshape(w-ww-m, top, ww, y+2); 

	sctext   .reshape(m*2+lw, top+y+y*2, w-m*2-lw, h-top-y-y*2-m);

	return 0L;
}


// SolFinger Main
void	Main(int argc, char** argv)
{
	static char* appClass = "SolFinger";
	Application applet(appClass, argc, argv);

	Args args;
	args.set(XmNclassName, appClass);
	args.set(XmNexStyle, (ulong)WS_EX_CLIENTEDGE);
	args.set(XmNbackground, (ulong)(COLOR_BTNFACE+1));
	args.set(XmNexStyle, (ulong)WS_EX_CONTROLPARENT);

	SolFinger solFinger(applet, appClass, args);
	solFinger.realize();
	applet.run();	
}

