Angus Leeming <[EMAIL PROTECTED]> writes:

| Lars Gullik Bj�nnes wrote:
>> So no substantial objections to this patch then?
>
| Q (Angus): Do things continue to work after your patch is applied?
| A (Lars): Of course, or else I would not be suggesting applying this patch.

So you are saying that I should at least compile and test it :-)

Here is an updated patch as well, gets rid fo the data_recieved
function in qt socket_callback.

Index: lyxsocket.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxsocket.h,v
retrieving revision 1.2
diff -u -p -r1.2 lyxsocket.h
--- lyxsocket.h	3 Apr 2004 08:36:59 -0000	1.2
+++ lyxsocket.h	18 Jul 2004 11:38:22 -0000
@@ -17,12 +17,15 @@
 #include "support/socktools.h"
 #include "lyxfunc.h"
 
+#include <boost/shared_ptr.hpp>
+
 #include <string>
-#include <set>
+#include <map>
 
 class LyXServerSocket;
 class LyXDataSocket;
 
+
 /** Sockets can be in two states: listening and connected.
  *  Connected sockets are used to transfer data, and will therefore
  *  be called Data Sockets. Listening sockets are used to create
@@ -32,24 +35,22 @@ class LyXDataSocket;
  * This class encapsulates local (unix) server socket operations and
  * manages LyXDataSockets objects that are created when clients connect.
  */
-class LyXServerSocket
-{
+class LyXServerSocket {
 public:
+	///
 	LyXServerSocket(LyXFunc *, std::string const &);
+	///
 	~LyXServerSocket();
-	/// File descriptor of the socket
-	int fd() const;
 	/// Address of the local socket
 	std::string const & address() const;
 	/// To be called when there is activity in the server socket
 	void serverCallback();
 	/// To be called when there is activity in the data socket
-	void dataCallback(LyXDataSocket *);
-
+	void dataCallback(int fd);
 private:
-	/// Close the connection to the argument client
-	void close(LyXDataSocket *);
-
+	///
+	void writeln(std::string const &);
+	///
 	LyXFunc * func;
 	/// File descriptor for the server socket
 	int fd_;
@@ -60,37 +61,32 @@ private:
                 MAX_CLIENTS = 10
         };
 	/// All connections
-	std::set<LyXDataSocket *> clients;
+	std::map<int, boost::shared_ptr<LyXDataSocket> > clients;
 };
 
 
 /** This class encapsulates data socket operations.
  *  It provides read and write IO operations on the socket.
  */
-class LyXDataSocket
-{
+class LyXDataSocket {
 public:
-	LyXDataSocket(LyXServerSocket *);
+	///
+	LyXDataSocket(int fd);
+	///
 	~LyXDataSocket();
-	/// The object that allocated us
-	LyXServerSocket * server() const;
-	/// File descriptor of the connection
-	int fd() const;
 	/// Connection status
 	bool connected() const;
 	/// Line buffered input from the socket
 	bool readln(std::string &);
 	/// Write the string + '\n' to the socket
 	void writeln(std::string const &);
-
 private:
-	LyXServerSocket * server_;
 	/// File descriptor for the data socket
 	int fd_;
 	/// True if the connection is up
 	bool connected_;
 	/// buffer for input data
-	std::string buffer;
+	std::string buffer_;
 };
 
 #endif // LYXSOCKET_H
Index: lyxsocket.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxsocket.C,v
retrieving revision 1.4
diff -u -p -r1.4 lyxsocket.C
--- lyxsocket.C	5 Nov 2003 10:49:07 -0000	1.4
+++ lyxsocket.C	18 Jul 2004 11:38:22 -0000
@@ -24,9 +24,11 @@
 #include "support/lyxlib.h"
 #include "support/socktools.h"
 
-#include <iostream>
+#include <boost/bind.hpp>
+
 #include <cerrno>
 
+using boost::shared_ptr;
 
 using std::auto_ptr;
 using std::endl;
@@ -38,7 +40,7 @@ using std::string;
 // that can connect at the same time.
 LyXServerSocket::LyXServerSocket(LyXFunc * f, string const & addr)
 	: func(f),
-	  fd_(lyx::support::socktools::listen(addr, MAX_CLIENTS)),
+	  fd_(lyx::support::socktools::listen(addr, 3)),
 	  address_(addr)
 {
 	if (fd_ == -1) {
@@ -52,7 +54,11 @@ LyXServerSocket::LyXServerSocket(LyXFunc
 	// Needed by lyxclient
 	lyx::support::putenv("LYXSOCKET", address_);
 
-	lyx_gui::set_serversocket_callback(this);
+	lyx_gui::register_socket_callback(
+		fd_,
+		boost::bind(&LyXServerSocket::serverCallback, *this)
+		);
+
 	lyxerr[Debug::LYXSERVER] << "lyx: New server socket "
 				 << fd_ << ' ' << address_ << endl;
 }
@@ -61,19 +67,13 @@ LyXServerSocket::LyXServerSocket(LyXFunc
 // Close the socket and remove the address of the filesystem.
 LyXServerSocket::~LyXServerSocket()
 {
+	lyx_gui::unregister_socket_callback(fd_);
 	::close(fd_);
 	lyx::support::unlink(address_);
-	while (!clients.empty()) close(*clients.rbegin());
 	lyxerr[Debug::LYXSERVER] << "lyx: Server socket quitting" << endl;
 }
 
 
-int LyXServerSocket::fd() const
-{
-	return fd_;
-}
-
-
 string const & LyXServerSocket::address() const
 {
 	return address_;
@@ -84,23 +84,36 @@ string const & LyXServerSocket::address(
 // is OK and if the number of clients does not exceed MAX_CLIENTS
 void LyXServerSocket::serverCallback()
 {
-	auto_ptr<LyXDataSocket> client(new LyXDataSocket(this));
-	if (client->connected()) {
-		if (clients.size() == MAX_CLIENTS) {
-			client->writeln("BYE:Too many clients connected");
-		} else {
-			lyx_gui::set_datasocket_callback(client.get());
-			clients.insert(client.release());
-			return;
-		}
+	int const client_fd = lyx::support::socktools::accept(fd_);
+
+	if (fd_ == -1) {
+		lyxerr[Debug::LYXSERVER] << "lyx: Failed to accept new client"
+					 << endl;
+		return;
 	}
+
+	if (clients.size() >= MAX_CLIENTS) {
+		writeln("BYE:Too many clients connected");
+		return;
+	}
+
+	// Register the new client.
+	clients[client_fd] =
+		shared_ptr<LyXDataSocket>(new LyXDataSocket(client_fd));
+	lyx_gui::register_socket_callback(
+		client_fd,
+		boost::bind(&LyXServerSocket::dataCallback,
+			    *this, client_fd)
+		);
 }
 
 
 // Reads and processes input from client and check
 // if the connection has been closed
-void LyXServerSocket::dataCallback(LyXDataSocket * client)
+void LyXServerSocket::dataCallback(int fd)
 {
+	shared_ptr<LyXDataSocket> client = clients[fd];
+
 	string line;
 	string::size_type pos;
 	bool saidbye = false;
@@ -133,17 +146,30 @@ void LyXServerSocket::dataCallback(LyXDa
 	}
 
 	if (saidbye || (!client->connected())) {
-		close(client);
+		clients.erase(fd);
 	}
 }
 
 
-// Removes client callback and deletes client object
-void LyXServerSocket::close(LyXDataSocket * client)
+void LyXServerSocket::writeln(string const & line)
 {
-	lyx_gui::remove_datasocket_callback(client);
-	clients.erase(client);
-	delete client;
+	string const linen(line + '\n');
+	int const size = linen.size();
+	int const written = ::write(fd_, linen.c_str(), size);
+	if (written < size) { // Allways mean end of connection.
+		if ((written == -1) && (errno == EPIPE)) {
+			// The program will also receive a SIGPIPE
+			// that must be caught
+			lyxerr << "lyx: Server socket " << fd_
+			       << " connection closed while writing." << endl;
+		} else {
+			// Anything else, including errno == EAGAIN, must be
+			// considered IO error. EAGAIN should never happen
+			// when line is small
+			lyxerr << "lyx: Server socket " << fd_
+			     << " IO error: " << strerror(errno);
+		}
+	}
 }
 
 // Debug
@@ -152,44 +178,27 @@ void LyXServerSocket::close(LyXDataSocke
 //	lyxerr << "LyXServerSocket debug dump.\n"
 //	     << "fd = " << fd_ << ", address = " << address_ << ".\n"
 //	     << "Clients: " << clients.size() << ".\n";
-//	if (!clients.empty()) {
-//		std::set<LyXDataSocket *>::const_iterator client = clients.begin();
-//		std::set<LyXDataSocket *>::const_iterator end = clients.end();
-//		for (; client != end; ++client)
-//			lyxerr << "fd = " << (*client)->fd() << "\n";
-//	}
+//	std::map<int, shared_ptr<LyXDataSocket> >::const_iterator client = clients.begin();
+//	std::map<int, shared_ptr<LyXDataSocket> >::const_iterator end = clients.end();
+//	for (; client != end; ++client)
+//		lyxerr << "fd = " << client->first << '\n';
 // }
 
 
-LyXDataSocket::LyXDataSocket(LyXServerSocket * serv)
-	:server_(serv),
-	 fd_(lyx::support::socktools::accept(serv->fd()))
+LyXDataSocket::LyXDataSocket(int fd)
+	: fd_(fd), connected_(true)
 {
-	if (fd_ == -1) {
-		connected_ = false;
-	} else {
-		lyxerr[Debug::LYXSERVER] << "lyx: New data socket " << fd_ << endl;
-		connected_ = true;
-	}
+	lyxerr[Debug::LYXSERVER] << "lyx: New data socket " << fd_ << endl;
 }
 
 
 LyXDataSocket::~LyXDataSocket()
 {
 	::close(fd_);
-	lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_ << " quitting." << endl;
-}
 
-
-LyXServerSocket * LyXDataSocket::server() const
-{
-	return server_;
-}
-
-
-int LyXDataSocket::fd() const
-{
-	return fd_;
+	lyx_gui::unregister_socket_callback(fd_);
+	lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_ << " quitting."
+				 << endl;
 }
 
 
@@ -205,12 +214,10 @@ bool LyXDataSocket::readln(string & line
 	int const charbuf_size = 100;
         char charbuf[charbuf_size]; // buffer for the ::read() system call
 	int count;
-	string::size_type pos;
 
 	// read and store characters in buffer
 	while ((count = ::read(fd_, charbuf, charbuf_size - 1)) > 0) {
-		charbuf[count] = '\0'; // turn it into a c string
-		buffer += charbuf;
+		buffer_.append(charbuf, charbuf + count);
 	}
 
 	// Error conditions. The buffer must still be
@@ -226,13 +233,14 @@ bool LyXDataSocket::readln(string & line
 	}
 
 	// Cut a line from buffer
-	if ((pos = buffer.find('\n')) == string::npos) {
+	string::size_type pos = buffer_.find('\n');
+	if (pos == string::npos) {
 		lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_
 					 << ": line not completed." << endl;
 		return false; // No complete line stored
 	}
-	line = buffer.substr(0, pos);
-	buffer = buffer.substr(pos + 1);
+	line = buffer_.substr(0, pos);
+	buffer_.erase(0, pos + 1);
 	return true;
 }
 
@@ -240,9 +248,9 @@ bool LyXDataSocket::readln(string & line
 // Write a line of the form <key>:<value> to the socket
 void LyXDataSocket::writeln(string const & line)
 {
-	string linen(line + '\n');
-	int size = linen.size();
-	int written = ::write(fd_, linen.c_str(), size);
+	string const linen(line + '\n');
+	int const size = linen.size();
+	int const written = ::write(fd_, linen.c_str(), size);
 	if (written < size) { // Allways mean end of connection.
 		if ((written == -1) && (errno == EPIPE)) {
 			// The program will also receive a SIGPIPE
Index: frontends/lyx_gui.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/lyx_gui.h,v
retrieving revision 1.24
diff -u -p -r1.24 lyx_gui.h
--- frontends/lyx_gui.h	13 Oct 2003 12:25:10 -0000	1.24
+++ frontends/lyx_gui.h	18 Jul 2004 11:38:22 -0000
@@ -15,6 +15,8 @@
 
 #include "FuncStatus.h"
 
+#include <boost/function.hpp>
+
 #include <string>
 #include <vector>
 
@@ -98,6 +100,7 @@ bool font_available(LyXFont const & font
 void set_read_callback(int fd, LyXComm * comm);
 void set_datasocket_callback(LyXDataSocket *);
 void set_serversocket_callback(LyXServerSocket *);
+void register_socket_callback(int fd, boost::function<void()> func);
 
 /**
  * remove a I/O read callback
@@ -106,6 +109,7 @@ void set_serversocket_callback(LyXServer
 void remove_read_callback(int fd);
 void remove_datasocket_callback(LyXDataSocket *);
 void remove_serversocket_callback(LyXServerSocket *);
+void unregister_socket_callback(int fd);
 
 } // namespace lyx_gui
 
Index: frontends/xforms/lyx_gui.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/xforms/lyx_gui.C,v
retrieving revision 1.59
diff -u -p -r1.59 lyx_gui.C
--- frontends/xforms/lyx_gui.C	19 May 2004 15:11:37 -0000	1.59
+++ frontends/xforms/lyx_gui.C	18 Jul 2004 11:38:22 -0000
@@ -291,27 +291,26 @@ void start(string const & batch, vector<
 	lyxerr[Debug::GUI] << "Creating view: " << width << 'x' << height
 			   << '+' << xpos << '+' << ypos << endl;
 
-	boost::shared_ptr<XFormsView> view_ptr(new XFormsView(width, height));
-	LyX::ref().addLyXView(view_ptr);
+	boost::shared_ptr<XFormsView> view(new XFormsView(width, height));
+	LyX::ref().addLyXView(view);
 
-	XFormsView & view = *view_ptr.get();
-	view.show(xpos, ypos, "LyX");
-	view.init();
+	view->show(xpos, ypos, "LyX");
+	view->init();
 
 	// FIXME: some code below needs moving
 
-	lyxserver = new LyXServer(&view.getLyXFunc(), lyxrc.lyxpipes);
-	lyxsocket = new LyXServerSocket(&view.getLyXFunc(),
+	lyxserver = new LyXServer(&view->getLyXFunc(), lyxrc.lyxpipes);
+	lyxsocket = new LyXServerSocket(&view->getLyXFunc(),
 			  os::slashify_path(os::getTmpDir() + "/lyxsocket"));
 
 	vector<string>::const_iterator cit = files.begin();
 	vector<string>::const_iterator end = files.end();
 	for (; cit != end; ++cit)
-		view.view()->loadLyXFile(*cit, true);
+		view->view()->loadLyXFile(*cit, true);
 
 	// handle the batch commands the user asked for
 	if (!batch.empty())
-		view.getLyXFunc().dispatch(lyxaction.lookupFunc(batch));
+		view->getLyXFunc().dispatch(lyxaction.lookupFunc(batch));
 
 	// enter the event loop
 	while (!finished) {
@@ -398,21 +397,8 @@ void C_read_callback(int, void * data)
 	comm->read_ready();
 }
 
-extern "C"
-void C_datasocket_callback(int, void * data)
-{
-	LyXDataSocket * client = static_cast<LyXDataSocket *>(data);
-	client->server()->dataCallback(client);
 }
 
-extern "C"
-void C_serversocket_callback(int, void * data)
-{
-	LyXServerSocket * server = static_cast<LyXServerSocket *>(data);
-	server->serverCallback();
-}
-
-}
 
 void set_read_callback(int fd, LyXComm * comm)
 {
@@ -424,25 +410,34 @@ void remove_read_callback(int fd)
 	fl_remove_io_callback(fd, FL_READ, C_read_callback);
 }
 
-void set_datasocket_callback(LyXDataSocket * p)
-{
-	fl_add_io_callback(p->fd(), FL_READ, C_datasocket_callback, p);
-}
 
-void remove_datasocket_callback(LyXDataSocket * p)
+namespace {
+
+std::map<int, boost::function<void()> > socket_callbacks;
+
+extern "C"
+void C_socket_callback(int fd, void *)
 {
-	fl_remove_io_callback(p->fd(), FL_READ, C_datasocket_callback);
+	socket_callbacks[fd]();
 }
 
-void set_serversocket_callback(LyXServerSocket * p)
+
+} // NS anon
+
+
+void register_socket_callback(int fd, boost::function<void()> func)
 {
-	fl_add_io_callback(p->fd(), FL_READ, C_serversocket_callback, p);
+	socket_callbacks[fd] = func;
+	fl_add_io_callback(fd, FL_READ, C_socket_callback, 0);
 }
 
-void remove_serversocket_callback(LyXServerSocket * p)
+
+void unregister_socket_callback(int fd)
 {
-	fl_remove_io_callback(p->fd(), FL_READ, C_serversocket_callback);
+	fl_remove_io_callback(fd, FL_READ, C_socket_callback);
+	socket_callbacks.erase(fd);
 }
+
 
 string const roman_font_name()
 {
Index: frontends/qt2/lyx_gui.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/lyx_gui.C,v
retrieving revision 1.66
diff -u -p -r1.66 lyx_gui.C
--- frontends/qt2/lyx_gui.C	23 Jun 2004 14:04:09 -0000	1.66
+++ frontends/qt2/lyx_gui.C	18 Jul 2004 11:38:22 -0000
@@ -35,6 +35,7 @@
 // All is well if the namespace is visible first.
 #include <boost/signals/signal1.hpp>
 #include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
 
 #include "QtView.h"
 #include "io_callback.h"
@@ -57,6 +58,8 @@ using lyx::frontend::QtView;
 
 namespace os = lyx::support::os;
 
+using boost::shared_ptr;
+
 #ifndef CXX_GLOBAL_CSTD
 using std::exit;
 #endif
@@ -78,7 +81,7 @@ float getDPI()
 }
 
 map<int, io_callback *> io_callbacks;
-map<int, socket_callback *> socket_callbacks;
+map<int, shared_ptr<socket_callback> > socket_callbacks;
 
 } // namespace anon
 
@@ -250,9 +253,9 @@ FuncStatus getStatus(FuncRequest const &
 	// application can still be accessed without giving focus to
 	// the main window. In this case, we want to disable the menu
 	// entries that are buffer-related.
-	if (use_gui 
+	if (use_gui
 	    && qApp->activeWindow() != qApp->mainWidget()
-	    && !lyxaction.funcHasFlag(ev.action, LyXAction::NoBuffer)) 
+	    && !lyxaction.funcHasFlag(ev.action, LyXAction::NoBuffer))
 		flag.enabled(false);
 #endif
 
@@ -301,34 +304,17 @@ void remove_read_callback(int fd)
 }
 
 
-void set_datasocket_callback(LyXDataSocket * p)
+void register_socket_callback(int fd, boost::function<void()> func)
 {
-	socket_callbacks[p->fd()] = new socket_callback(p);
+	socket_callbacks[fd] = shared_ptr<socket_callback>(new socket_callback(fd, func));
 }
 
-void set_serversocket_callback(LyXServerSocket * p)
-{
-	socket_callbacks[p->fd()] = new socket_callback(p);
-}
-
-void remove_socket_callback(int fd)
-{
-	map<int, socket_callback *>::iterator it = socket_callbacks.find(fd);
-	if (it != socket_callbacks.end()) {
-		delete it->second;
-		socket_callbacks.erase(it);
-	}
-}
 
-void remove_datasocket_callback(LyXDataSocket * p)
+void unregister_socket_callback(int fd)
 {
-	remove_socket_callback(p->fd());
+	socket_callbacks.erase(fd);
 }
 
-void remove_serversocket_callback(LyXServerSocket * p)
-{
-	remove_socket_callback(p->fd());
-}
 
 string const roman_font_name()
 {
Index: frontends/qt2/socket_callback.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/socket_callback.h,v
retrieving revision 1.2
diff -u -p -r1.2 socket_callback.h
--- frontends/qt2/socket_callback.h	12 Dec 2003 11:40:45 -0000	1.2
+++ frontends/qt2/socket_callback.h	18 Jul 2004 11:38:22 -0000
@@ -18,9 +18,8 @@
 #include <qobject.h>
 #include <qsocketnotifier.h>
 #include <boost/scoped_ptr.hpp>
+#include <boost/function.hpp>
 
-class LyXServerSocket;
-class LyXDataSocket;
 
 /**
  * socket_callback - a simple wrapper for asynchronous socket notification
@@ -34,17 +33,12 @@ class socket_callback : public QObject {
 	Q_OBJECT
 public:
 	/// connect a connection notification from the LyXServerSocket
-	socket_callback(LyXServerSocket * server);
-	socket_callback(LyXDataSocket * data);
-public slots:
-	void server_received();
-	void data_received();
+	socket_callback(int fd, boost::function<void()> func);
 private:
 	/// our notifier
 	boost::scoped_ptr<QSocketNotifier> sn_;
-
-	LyXServerSocket * server_;
-	LyXDataSocket * data_;
+	/// The callback function
+	boost::function<void()> func_;
 };
 
 #endif // SOCKET_CALLBACK_H
Index: frontends/qt2/socket_callback.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/socket_callback.C,v
retrieving revision 1.3
diff -u -p -r1.3 socket_callback.C
--- frontends/qt2/socket_callback.C	20 May 2004 09:36:28 -0000	1.3
+++ frontends/qt2/socket_callback.C	18 Jul 2004 11:38:22 -0000
@@ -12,32 +12,12 @@
 
 #include <config.h>
 
-#include "lyxsocket.h"
 #include "socket_callback.h"
 
 
-socket_callback::socket_callback(LyXServerSocket * server)
-	: server_(server)
+socket_callback::socket_callback(int fd, boost::function<void()> func)
+	: func_(func)
 {
-	sn_.reset(new QSocketNotifier(server->fd(), QSocketNotifier::Read, this));
-	connect(sn_.get(), SIGNAL(activated(int)), this, SLOT(server_received()));
-}
-
-socket_callback::socket_callback(LyXDataSocket * data)
-	: data_(data)
-{
-	sn_.reset(new QSocketNotifier(data->fd(), QSocketNotifier::Read, this));
-	connect(sn_.get(), SIGNAL(activated(int)), this, SLOT(data_received()));
-}
-
-
-void socket_callback::server_received()
-{
-	server_->serverCallback();
-}
-
-
-void socket_callback::data_received()
-{
-	data_->server()->dataCallback(data_);
+	sn_.reset(new QSocketNotifier(fd, QSocketNotifier::Read, this));
+	connect(sn_.get(), SIGNAL(activated(int)), this, SLOT(func_()));
 }
Index: frontends/gtk/lyx_gui.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/gtk/lyx_gui.C,v
retrieving revision 1.15
diff -u -p -r1.15 lyx_gui.C
--- frontends/gtk/lyx_gui.C	19 May 2004 15:11:32 -0000	1.15
+++ frontends/gtk/lyx_gui.C	18 Jul 2004 11:38:22 -0000
@@ -49,6 +49,7 @@
 #include <iomanip>
 #include <fcntl.h>
 #include <boost/bind.hpp>
+#include <boost/function.hpp>
 
 //just for xforms
 #include "lyx_forms.h"
@@ -442,19 +443,12 @@ void lyx_gui::remove_read_callback(int f
 }
 
 
-void lyx_gui::set_datasocket_callback(LyXDataSocket * /* p */)
+void lyx_gui::register_socket_callback(int /*fd*/,
+				       boost::function<void()> /*func*/)
 {}
 
 
-void lyx_gui::remove_datasocket_callback(LyXDataSocket * /* p */)
-{}
-
-
-void lyx_gui::set_serversocket_callback(LyXServerSocket * /* p */)
-{}
-
-
-void lyx_gui::remove_serversocket_callback(LyXServerSocket * /* p */)
+void lyx_gui::unregister_socket_callback(int /*fd*/)
 {}
 
 
-- 
        Lgb

Reply via email to