// This may look like C code, but it is really -*- C++ -*-
// 
// <copyright> 
//  
//  Copyright (c) 1993 
//  Institute for Information Processing and Computer Supported New Media (IICM), 
//  Graz University of Technology, Austria. 
//  
// </copyright> 
// 
// 
// <file> 
// 
// Name:        rvwstuff.h
// 
// Purpose:     contains the ipc stuff between session manager and the different viewers
// 
// Created:     26 Jul 93   Joerg Faschingbauer
// 
// Modified:    
// 
// Description: The basic concept is that a HgViewer has a manager that tells him what 
//              to do (as specified there). Here the RemoteViewer is that part of a 
//              viewer that resides in the local part (i.e., the client of a remote 
//              viewer daemon). 
//              It has all the features of a HgViewer (of course, because it is a derived 
//              class), but it does no viewing by itself. It just passes the requests the 
//              HgViewerManager makes to a viewer daemon.
//              On the daemon side there is a RemoteViewerManager (which is a 
//              HgViewerManager also) which receives the ipc requests done by the 
//              RemoteViewer on the client side. That RemoteViewerManager controls the 
//              actual HgViewer.
//              On the other hand, when the HgViewer (the actual daemon-side one) want
//              to make a request to the Manager on the client side (the actual 
//              client-side one), this request is passed in the same but reverse manner 
//              over RemoteViewerManager and RemoteViewer. 
// 
// </file> 
#ifndef hg_viewer_rvwstuff_h
#define hg_viewer_rvwstuff_h

#include <hyperg/viewer/lib.h>

#include <hyperg/viewer/vwstuff.h>

#include <hyperg/utils/str.h>

#include <Dispatch/rpcreader.h>
#include <Dispatch/rpcwriter.h>
#include <Dispatch/rpcstream.h>

#include <sys/types.h>


class RpcHdr ;


class ToRViewerProtocol {
public:
   enum {
      READY,
         LOAD,
         BROWSE,
         TERMINATE,
         LOAD1,  // unused

         // X functions
         ICONIFY,
         DEICONIFY,
         MOVETO,
         RESIZE,
         MAP,
         UNMAP,
         RAISE,
         LOWER,

         SETLANG, 

         HOLDDOCUMENT,

         SAVERESOURCES,
         
         DOEDIT,
         NEWDOC,
         GETPOS,

         CANCELREQUEST,

         NFCNS
         } ;
} ;

class FromRViewerProtocol {
public:
   enum From {
      READY,
         FOLLOWLINK,
         ERROR,
         TERMINATED,
         ADDINFO, // unused
         DEFSRCANCH,
         DEFDESTANCH,
         DELLINK,
         SHOWREFERENCES,
         SHOWANNOTATIONS,
         SHOWPARENTS,
         SHOWATTRIBUTES,
         BACK,
         FORWARD,
         HISTORY,
         HOLD,
         EDIT,
         UPLOAD,
         CANCELEDIT,
         STRING, // sometimes a string return value is wanted
         MODIFYATTRIBUTE,
         RELOADDOCUMENT,
         NFCNS
         } ;
} ;




// <class> 
//  
// Name:             HgViewerDaemon
// 
// Purpose:          used on the client side to comfortably start a and make a connection 
//                   to a viewer daemon
// 
// Public Interface: HgViewerDaemon()
//                      default constructor
// 
//                   HgViewerDaemon (const RString&)
//                      no default constructor
// 
//                   boolean start() 
//                      start the viewer daemon which is defined by binary 
//                      (i.e., the code to execute)
// 
//                   boolean running() const
//                   void quit()
//                      ...
// 
//                   void binary (const RString&)
//                      set the code that should be executed when starting
// 
//                   const RString& host() const      return localhost
//                   int port() const     return port
//                   int pid() const      return process id
// 
// Description:      A port is created and fork() and exec() is done when start()'ing the daemon. 
//                   exec passes as arguments the port number. The daemon then creates a port 
//                   on his side, connects to the client side port, and sends its port number 
//                   to the client. After doing this, the daemon->client connection and the 
//                   client side port are closed.
// 
// </class> 
class HgViewerDaemon : public IOHandler {
public:
   HgViewerDaemon (int timeout=30) ;
   HgViewerDaemon (const RString& binary, int timeout=30) ;
   ~HgViewerDaemon() ;

   boolean start() ;
   boolean running() const { return running_; }
   void    quit() ;

   void binary (const RString& b) { binary_ = b; }

   const RString& host() const { return host_; }
   int port() const { return port_; }
   pid_t pid() const { return pid_; }

   virtual int inputReady (int) ;

private:
   boolean running_ ;
   RString binary_ ;
   RString host_ ;
   int port_ ;
   pid_t pid_ ;
   int timeout_ ;
   rpcstream init_port_ ;

   // access denied since one object of HgViewerDaemon is associated with one 
   // process ("if and only if")
   HgViewerDaemon (const HgViewerDaemon&) {}
   HgViewerDaemon& operator=(const HgViewerDaemon&) {return *this;}
} ;









class LocalWriter ;
class LocalReader ;
// **********************************************************
// class RemoteViewer
// **********************************************************
class RemoteViewer : public HgViewer {
public:
   RemoteViewer (HgViewerDaemon&, HgViewerManager*, 
                 int timeout=15) ;
   RemoteViewer (const char* host, int port, HgViewerManager*, 
                 int timeout=15) ;
   virtual ~RemoteViewer() ;

   virtual void load (const char* doc, const char* anchors, char* info=nil) ;
   virtual void browse (const char* dest) ;
   virtual void terminate() ;

   virtual void cancelRequest (const char*) ;

   virtual void holdDocument (const char*) ;
   virtual void iconify() ;
   virtual void deiconify() ;
   virtual void moveto (float x, float y) ;
   virtual void resize (float x, float y) ;
   virtual void map() ;
   virtual void unmap() ;
   virtual void raise() ;
   virtual void lower() ;

   virtual void setLanguage (HgLanguage::Language l) ;

   virtual void saveResources() ;

   virtual void doEdit (const RString& object, const RString& anchors) ;
   virtual void newDoc (int refno, const RString& info) ;
   virtual void getPos (RString&) ;

   virtual int port() const ;

   static const boolean binary ;

private:
   void open_if_appropriate_() ;

private:
   friend class LocalReader ;

   LocalWriter* writer_ ;
   LocalReader* reader_ ;

   boolean running_ ;
   boolean ready_ ;
   int doc_port_ ; // port on which to receive documents
   RString string_ ;
   boolean propagate_errors_ ;
} ;

// **********************************************************
// class LocalWriter
// **********************************************************
class LocalWriter : public RpcWriter, virtual public ToRViewerProtocol {
public:
   LocalWriter (const char* host, int port, boolean fatal, boolean binary) ;

   void sendReady() ;
   void sendLoad (const char* doc, const char* anchors) ;
   void sendLoad1 (const char* doc, const char* anchors) ;
   void sendBrowse (const char* dest) ;
   void sendTerminate() ;

   void sendCancelRequest (const char*) ;

   void sendHoldDocument (const char*) ;
   void sendIconify() ;
   void sendDeiconify() ;
   void sendMoveto (float x, float y) ;
   void sendResize (float x, float y) ;
   void sendMap() ;
   void sendUnmap() ;
   void sendRaise() ;
   void sendLower() ;

   void sendSetLanguage (int l) ;

   void sendSaveResources() ;

   void sendDoEdit (const RString& object, const RString& anchors) ;
   void sendNewDoc (int refno, const RString& info) ;
   void sendGetPos() ;
} ;



// **********************************************************
// class LocalReader
// **********************************************************
class LocalReader : public RpcReader, virtual public FromRViewerProtocol {
public:
   LocalReader (rpcstream* stream, RemoteViewer* viewer) ;

   void terminated (boolean t) { viewer_terminated_ = t; }

protected:
   virtual int  inputReady (int fd) ;
   virtual void connectionClosed(int) ;
   virtual void timerExpired(long, long) ;

   // receive response to a ready request
   static void receive_READY      (RpcReader*, RpcHdr&, rpcstream&) ;

   // receive calls from a HgViewer to the HgViewerManager
   static void receive_FOLLOWLINK (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_ERROR (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_TERMINATED (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_ADDINFO (RpcReader*, RpcHdr&, rpcstream&) ; // unused
   static void receive_DEFSRCANCH (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_DEFDESTANCH(RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_DELLINK (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_SHOWREFERENCES (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_SHOWANNOTATIONS (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_SHOWPARENTS (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_SHOWATTRIBUTES (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_BACK (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_FORWARD (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_HISTORY (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_HOLD (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_EDIT (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_UPLOAD (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_CANCELEDIT (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_STRING (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_MODIFYATTRIBUTE (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_RELOADDOCUMENT (RpcReader*, RpcHdr&, rpcstream&) ;

private:
   RemoteViewer* viewer_ ;
   boolean viewer_terminated_ ;  // on receipt of connectionClosed look at this one:
                                 // don't report an error to your boss if the viewer
                                 // has terminated regularly (also a reason for conn.Cl.)
} ;









class RemoteWriter ;
class RemoteReader ;
// **********************************************************
// class RemoteViewerManager
// **********************************************************
class RemoteViewerManager : public HgViewerManager {
public:
   RemoteViewerManager (int fd) ;
   virtual ~RemoteViewerManager() ;

   virtual void followLink (const RString&, HgViewer*) ;
   virtual void viewerError (HgViewer*) ;
   virtual void viewerTerminated (const RString&, HgViewer*) ;

   virtual void defineSourceAnchor (const RString&, HgViewer*) ;
   virtual void defineDestAnchor (const RString&, HgViewer*) ;

   virtual void deleteLink (const RString&, HgViewer*) ;

   virtual void showReferences (const RString& object, HgViewer*) ;
   virtual void showParents (const RString& object, HgViewer*) ;
   virtual void showAnnotations (const RString& object, HgViewer*) ;
   virtual void showAttributes (const RString& object, HgViewer*) ;

   virtual void back (HgViewer*) ;
   virtual void forward (HgViewer*) ;

   virtual void history (HgViewer*) ;

   virtual void hold (const RString& object, HgViewer*) ;

   virtual void edit (const RString& object, HgViewer*) ;
   virtual void upload (const RString& object, const RString& anchors,
                        const RString& host, int port,
                        HgViewer*, int refno=-1) ;
   virtual void cancelEdit (const RString& object, HgViewer*) ;
   virtual void modifyAttribute(const RString&) ;
   virtual void reloadDocument (const RString&) ;


   RemoteReader* reader()    { return _reader; }
   RemoteWriter* writer()    { return _writer; }
   HgViewer*     viewer()    { return _viewer; }
   void viewer (HgViewer* viewer) ;

   static const boolean binary ;

private:
   RemoteReader* _reader ;
   RemoteWriter* _writer ;
   HgViewer* _viewer ;
} ;


// **********************************************************
// class RemoteWriter
// **********************************************************
class RemoteWriter : public RpcWriter, virtual public FromRViewerProtocol {
public:
   RemoteWriter (int fd) ;
   ~RemoteWriter () {}
   
   void sendReady (int port, const RString& options) ;
   void sendFollowLink (const RString&) ;
   void sendError (HgViewer::VwError) ;
   void sendTerminated (const RString& obj) ;
   void sendAddInfo (const RString& info) ; // unused

   void sendDefineSourceAnchor (const RString&) ;
   void sendDefineDestAnchor (const RString&) ;

   void sendDeleteLink (const RString& link) ;

   void sendShowReferences (const RString& object) ;
   void sendShowAnnotations (const RString& object) ;
   void sendShowParents (const RString& object) ;
   void sendShowAttributes (const RString& object) ;

   void sendBack() ;
   void sendForward() ;
   void sendHistory() ;
   
   void sendHold (const RString& object) ;

   void sendEdit (const RString& object) ;
   void sendUpload (const RString& object, const RString& anchors, 
                    const RString& host, int port, int refno) ;
   void sendCancelEdit (const RString& object) ;
   void sendModifyAttribute (const RString& object) ;
   void sendReloadDocument (const RString& object) ;
   void sendString (const RString&) ;
} ;



// **********************************************************
// class RemoteReader
// **********************************************************
class RemoteReader : public RpcReader, virtual public ToRViewerProtocol {
public:
   RemoteReader (rpcstream*, RemoteViewerManager*) ;
   virtual ~RemoteReader () {}
   
   void 	run() ;
   void 	quitRunning() ;
   
   RemoteViewerManager* manager() { return manager_; } ;

protected:
//   virtual int  inputReady (int fd) ;
   virtual void connectionClosed (int fd) ;

private:
   RemoteViewerManager* manager_ ;
   boolean running_ ;
   
   static void receive_READY (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_PORT (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_LOAD (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_LOAD1 (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_BROWSE (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_TERMINATE (RpcReader*, RpcHdr&, rpcstream&) ;

   static void receive_CANCELREQUEST (RpcReader*, RpcHdr&, rpcstream&) ;

   static void receive_HOLDDOCUMENT (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_ICONIFY (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_DEICONIFY (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_MOVETO (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_RESIZE (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_MAP (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_UNMAP (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_RAISE (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_LOWER (RpcReader*, RpcHdr&, rpcstream&) ;

   static void receive_SETLANG (RpcReader*, RpcHdr&, rpcstream&) ;

   static void receive_SAVERESOURCES (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_DOEDIT (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_NEWDOC (RpcReader*, RpcHdr&, rpcstream&) ;
   static void receive_GETPOS (RpcReader*, RpcHdr&, rpcstream&) ;
} ;




#endif
