#ifndef KPSWIDGET_H
#define KPSWIDGET_H

#include <kprocess.h>

#include <qfiledialog.h>
#include <stdlib.h>
#include <math.h>
#include <qapplication.h>
#include <qwidget.h>
#include <qpainter.h>
#include <qpaintdevice.h>
#include <qpoint.h>
#include <qqueue.h>
#include <qscrollview.h>
#include <qbitmap.h>
#include <qsocketnotifier.h>
#define	 GC GC_QQQ				// avoid type mismatch
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <ctype.h>

#include "kdsc.h"
#include "messages.h"
class InterpreterDialog;

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#ifndef None
#define None -1
#endif

#ifndef XlibSpecificationRelease
typedef char *XPointer;
#endif

#ifndef SEEK_SET
#define SEEK_SET 0
#endif

#ifndef XlibSpecificationRelease
typedef char *XPointer;
#endif

#include <errno.h>
/* BSD 4.3 errno.h does not declare errno */
extern int errno;
/* Both error returns are checked for non-blocking I/O. */
/* Manufacture the other error code if only one exists. */
#if !defined(EWOULDBLOCK) && defined(EAGAIN)
#define EWOULDBLOCK EAGAIN
#endif
#if !defined(EAGAIN) && defined(EWOULDBLOCK)
#define EAGAIN EWOULDBLOCK
#endif

class KPSWidget : public QWidget
{
    Q_OBJECT

public:
    KPSWidget( QWidget *parent = 0, const char* name = 0 );
    ~KPSWidget();

    
    void enableInterpreter();
    void disableInterpreter();
    
    bool isInterpreterReady() const; 
    bool isInterpreterRunning() const;
    
    bool nextPage();
    bool sendPS( FILE* fp, const KDSC::Offset&, bool close);
    
    void setFileName( const QString& );

    
    void layout();
    void relayout();
    void setDelayedLayout( bool );
    
    void setBoundingBox( const KDSC::BoundingBox& );
    KDSC::BoundingBox boundingBox() const { return _boundingBox; }
    
    void setOrientation( int orientation );
    int orientation() const { return _orientation; }
    
    void setResolution( int xdpi, int ydpi);
    
    
    bool configure();
    void writeSettings();
	
signals:
    void pageSizeChanged( QSize );

protected:    
    struct Record {
	~Record() { if( close ) fclose( fp ); }
	FILE* fp;
	long begin;
	unsigned int len;
	bool seek_needed;
	bool close;
    };
	
    bool x11Event( XEvent* );
    
    void setup();
    bool computeSize();
    
    void startInterpreter();
    void stopInterpreter();

protected slots:
    void gs_input();
    void gs_output(KProcess *, char *buffer, int len);
    void interpreterFailed();
	
private:
    Window _mWin;   // Destination of ghostscript messages.
    
    Display*	gs_display;
    Window	gs_window;
    
    Atom gs_colors, ghostview, gs_next, gs_page, gs_done;
    
    /**
     * Variables used to communicate with the gs process.
     */
    Pixmap  background_pixmap;
    int	    orient_angle;
    KDSC::BoundingBox _boundingBox;
    float   _xdpi, _ydpi;
    int	    left_margin, right_margin, bottom_margin, top_margin;
    
    MessagesDialog*	messages;
    InterpreterDialog*	intConfig;

    KProcess*	    proc;
 
    QQueue<Record>  _inputQueue;
    char*	    input_buffer;
    unsigned int    bytes_left;
    bool	    stdin_ready;
    
    bool busy;
    int _orientation;
    bool antialias;
    bool show_messages;
    QString _fileName;
    int foreground, background_pixel;

    // Some flags
    bool _interpreterReady;
    bool _disableStart;	    // Disables starting the interpreter.
    bool _delayedLayout;    
    bool _layoutDirty;
};

class KPSView : public QScrollView
{
    Q_OBJECT

public:
    KPSView( QWidget* parent = 0, const char* name = 0 );
    ~KPSView() { ; }

    KPSWidget* psWidget() const { return _psWidget; }

    void enableScrollBars( bool);
    
    bool eventFilter( QObject*, QEvent* );
    
public slots:
    bool readDown();
    void scrollUp();
    void scrollDown();
    void scrollRight();
    void scrollLeft();
    void scrollTop();
   
signals:
    void viewSizeChanged( QSize size );
    
protected:
    void keyPressEvent( QKeyEvent* );
    void viewportResizeEvent( QResizeEvent* );
    void centerContents();
    
private:
    QPoint _dragGrabPos;
    
    KPSWidget* _psWidget;
};

#endif // KPSWIDGET_H

