/*
 * This file is part of the apvlv package
 *
 * Copyright (C) 2008 Alf.
 *
 * Contact: Alf <naihe2010@126.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2.0 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */
/* @PPCPPFILE ApvlvDoc.h
 *
 *  Author: Alf <naihe2010@126.com>
 */
/* @date Created: 2008/09/30 00:00:00 Alf */

#ifndef _APVLV_DOC_H_
#define _APVLV_DOC_H_

#include "ApvlvFile.h"
#include "ApvlvCore.h"
#include "ApvlvUtil.h"

#include <gtk/gtk.h>

//#include <cstdlib>
#include <iostream>
#include <vector>
#include <map>
#include <list>

using namespace std;

namespace apvlv
{
  struct PrintData
  {
    ApvlvFile *file;
    guint frmpn, endpn;
  };

  struct ApvlvDocPosition
  {
    int pagenum;
    double scrollrate;
  };

  typedef map < char, ApvlvDocPosition > ApvlvDocPositionMap;

  struct ApvlvWord
  {
    ApvlvPos pos;
    string word;
  };

  struct ApvlvLine
  {
    ApvlvPos pos;
    vector < ApvlvWord > mWords;
  };

  class ApvlvDoc;
  class ApvlvDocCache
  {
  public:
    ApvlvDocCache (ApvlvFile *);

    ~ApvlvDocCache ();

    void set (guint p, double zm, guint rot, bool delay = true);

    static void load (ApvlvDocCache *);

    PopplerPage *getpage ();

    guint getpagenum ();

    guchar *getdata (bool wait);

    GdkPixbuf *getbuf (bool wait);

    double getwidth ();

    double getheight ();

    ApvlvLinks *getlinks ();

    bool canselect ();
    bool mInverted;

    ApvlvWord *getword (int x, int y);

    ApvlvLine *getline (double x, double y);

  private:
    ApvlvFile * mFile;
    ApvlvLinks *mLinks;
    double mZoom;
    double mRotate;
    gint mPagenum;
    guchar *mData;
    gint mSize;
    GdkPixbuf *mBuf;
    gint mWidth;
    gint mHeight;

    vector < ApvlvLine > *mLines;

    void preparelines (double x1, double y1, double x2, double y2);
    ApvlvPos prepare_add (ApvlvPos & last, ApvlvPoses * results,
			  const char *word);
  };

  class ApvlvDocStatus:public ApvlvCoreStatus
  {
  public:
    ApvlvDocStatus (ApvlvDoc *);

    ~ApvlvDocStatus ();

    void active (bool act);

    void setsize (int, int);

    void show ();

  private:
    ApvlvDoc * mDoc;
#define AD_STATUS_SIZE   4
    GtkWidget *mStlab[AD_STATUS_SIZE];
  };

  class ApvlvDoc:public ApvlvCore
  {
  public:
    ApvlvDoc (int w, int h, const char *zm = "NORMAL", bool cache = false);

    ~ApvlvDoc ();

    void setactive (bool act);

    ApvlvDoc *copy ();

    bool usecache ();

    void usecache (bool use);

    bool loadfile (string & filename, bool check = true);

    bool loadfile (const char *src, bool check = true);

    int pagenumber ();

    bool print (int ct);

    bool totext (const char *name);

    bool rotate (int ct = 90);

    void markposition (const char s);

    void setzoom (const char *z);

    void jump (const char s);

    void showpage (int p, double s = 0.00);

    void nextpage (int times = 1);

    void prepage (int times = 1);

    void halfnextpage (int times = 1);

    void halfprepage (int times = 1);

    void scrollup (int times);
    void scrolldown (int times);
    void scrollleft (int times);
    void scrollright (int times);

    bool search (const char *str, bool reverse = false);

    bool continuous ();

    returnType process (int hastimes, int times, guint keyval);

    void gotolink (int ct);

    void returnlink (int ct);

  private:
    void blank (int x, int y);

    void blankarea (int x1, int y1, int x2, int y2, guchar *, int width,
		    int height);

    void blankaction (double x, double y);

    void togglevisual (int type);

    int yank (int times);

    void eventpos (double x, double y, double *rx, double *ry);

    returnType subprocess (int ct, guint key);

    bool status_show ();

    int convertindex (int p);

    void markselection ();

    bool needsearch (const char *str, bool reverse = false);

    void refresh ();

    bool reload ();

    bool savelastposition (const char *filename);

    bool loadlastposition (const char *filename);

    static void apvlv_doc_on_mouse (GtkAdjustment *, ApvlvDoc *);

    static gboolean apvlv_doc_first_scroll_cb (gpointer);

    static gboolean apvlv_doc_first_copy_cb (gpointer);

    static void apvlv_doc_button_event (GtkEventBox * box,
					GdkEventButton * ev, ApvlvDoc *);

    static void apvlv_doc_motion_event (GtkWidget *, GdkEventMotion *,
					ApvlvDoc *);

    static void apvlv_doc_copytoclipboard_cb (GtkMenuItem * item, ApvlvDoc *);

    static void begin_print (GtkPrintOperation * operation,
			     GtkPrintContext * context, PrintData * data);
    static void draw_page (GtkPrintOperation * operation,
			   GtkPrintContext * context,
			   gint page_nr, PrintData * data);
    static void end_print (GtkPrintOperation * operation,
			   GtkPrintContext * context, PrintData * data);

    static void apvlv_doc_monitor_callback (GFileMonitor *, GFile *, GFile *, GFileMonitorEvent, ApvlvDoc *);

    enum
    { VISUAL_NONE, VISUAL_V, VISUAL_CTRL_V };
    gint mInVisual;
    gint mBlankx1, mBlanky1;
    gint mBlankx2, mBlanky2;
    gint mLastpress;
    gint mCurx, mCury;

    ApvlvDocPositionMap mPositions;
    vector < ApvlvDocPosition > mLinkPositions;

    ApvlvDocCache *mCurrentCache1, *mCurrentCache2;
    ApvlvDocCache *newcache (int pagenum);
    void deletecache (ApvlvDocCache * ac);

    bool mAutoScrollPage;
    bool mAutoScrollDoc;
    bool mContinuous;

    // image viewer
    GtkWidget *mImage1, *mImage2;
  };

}

#endif

/* Local Variables: */
/* mode: c++ */
/* End: */
