#ifndef KPSWIDGET_H
#define KPSWIDGET_H

#include <qfiledialog.h>
#include <stdlib.h>
#include <math.h>
#include <qapplication.h>
#include <qwidget.h>
#include <qpainter.h>
#include <qpaintdevice.h>
#include <qscrollbar.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 "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 <signal.h>
#ifdef SIGNALRETURNSINT
#define SIGVAL int
#else
#define SIGVAL void
#endif

#include <fcntl.h>
/* if POSIX O_NONBLOCK is not available, use O_NDELAY */
#if !defined(O_NONBLOCK) && defined(O_NDELAY)
#define O_NONBLOCK O_NDELAY
#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

#define NUM_ARGS 100;
#if !defined(BUFSIZ)
#define BUFSIZ 512;
#endif

struct record_list {
    FILE *fp;
    long begin;
    unsigned int len;
    bool seek_needed;
    bool close;
    struct record_list *next;
};

class KFVWidget : public QWidget
{
  Q_OBJECT;

 public:
  KFVWidget (QWidget *parent);

 signals:
  void moveOffset (int x, int y);

 protected:
  int dragstartx, dragstarty;
  int draglastx, draglasty;
  int startoffx, startoffy;

  void mousePressEvent (QMouseEvent *);
  void mouseMoveEvent (QMouseEvent *);

};


class KPSWidget : public QWidget
{
    Q_OBJECT

public:
	KPSWidget(QWidget *parent);
	~KPSWidget();


	QScrollBar *hScrollBar() {return vertScrollBar;}
	QScrollBar *vScrollBar() {return horScrollBar;}
	
	Atom 		gs_colors, ghostview, next, gs_page, done;
	Display 	*gs_display;
	Window 		gs_window;
	bool 		busy;
	Window 		mwin;
	Pixmap background_pixmap;
	
	
	bool sendPS(FILE *fp, long begin,unsigned int len,bool close);
	void layout();
	void setDocumentPresent( bool state );
	void disableInterpreter();
	void enableInterpreter();
	bool isInterpreterReady();
	bool isInterpreterRunning();
	bool nextPage();

	/**
	 * Emit size/pos message to sync up the scroll box.
	 *  (Doesn't seem to help much.)
	 **/
	//	void sync(); 
	
	QWidget *fullView;
	QScrollBar *vertScrollBar;
	QScrollBar *horScrollBar;
	QWidget *patch;
	QFrame *pageFrame;
	QFrame *topFrame;
	QFrame *leftFrame;
	QFrame *rightFrame;
	QFrame *bottomFrame;

	
	void scrollLeft();
	void scrollRight();
	void scrollUp();
	void scrollDown();
	void scrollTop();
	bool readDown();
	
	void movePage();
	bool configure();
	void writeSettings();
	
	int orient_angle;
	int orientation;
	bool	antialias;
	bool show_messages;
	bool	changed;
	bool disable_start;
	QString filename;
	int llx, lly, urx, ury;
	int left_margin, right_margin, bottom_margin, top_margin;
	int foreground, background_pixel;
	float xdpi, ydpi;
	int  scroll_x_offset, scroll_y_offset;
		
public slots:
	void gs_input();
	void gs_output(int source);
	void slotVertScroll( int value );
	void slotHorScroll( int value );
	void slotScroll( QPoint point );

protected:

	void resizeEvent(QResizeEvent *);
	void paintEvent(QPaintEvent *);
	void wheelEvent(QWheelEvent *);


	void setup();
	void startInterpreter();
	void stopInterpreter();
	void interpreterFailed();
	bool computeSize();

signals:
        void pageSizeChanged( QSize size );
	void viewSizeChanged( QSize size );
	void currentPosChanged( QPoint point );
	
private:
	MessagesDialog *messages;
	InterpreterDialog *intConfig;

	QSocketNotifier *sn_input;
	QSocketNotifier *sn_output;
	QSocketNotifier *sn_error;
	
	
	bool mDocumentPresent;
	int  clip_x, clip_y, clip_width, clip_height;
	
	const char *gs_call[100];
	int gs_arg;
	int interpreter_pid;
	struct record_list *ps_input;	
	char *input_buffer;	
	unsigned int bytes_left;	
	char *input_buffer_ptr; 
	unsigned int buffer_bytes_left; 
	int	interpreter_input_id;
	int interpreter_input;
	int interpreter_output_id;
	int interpreter_error_id;
	int	interpreter_output; 
	int	interpreter_error;	
	char *buf;
	int ret;
	int	std_in[2];
	int	std_out[2];
	int	std_err[2];
	
}; 

#endif // KPSWIDGET_H


