/*  
	BeOS Front-end du PDF file reader xpdf.
    Copyright (C) 1998 Hubert Figuiere
	Copyright (C) 2000 Michael Pfeiffer
	
    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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
//
// BepdfApplication.cpp
//
// (c)1998 Hubert Figuiere
//
// 


#include <stdlib.h>

#include <app/Application.h>
#include <storage/FilePanel.h>
#include <Screen.h>

#include <gtypes.h>
#include <parseargs.h>
#include <Alert.h>
#include "config.h"
#include "Params.h"
#include "Error.h"

#include "PDFWindow.h"
#include "BepdfApplication.h"
#include "StatusWindow.h"

static const char * cvsid = "$Id: BepdfApplication.cpp,v 1.3 1999/02/03 21:48:29 hub Exp $";

static const char * bePDFVersion = "0.6.0";
static const char * bePDFCopyright = "BeOS code (c) 1999 Hubert Figuiere\n";

static const char * pdfViewerVersion = "0.2.1";
static const char * pdfViewerCopyright = 
    "BeOS 5 port (c) 2000 Michael Pfeiffer\n"
    "Japanese Font Support (c) 2000 NAITOH Jun\n"
    "\n"
    "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 of the License, or "
    "(at your option) any later version.\n"
	"\n"
    "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.\n"
	"\n"
    "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., 675 Mass Ave, Cambridge, MA 02139, USA.";
    
static const char * PAGE_NUM_MSG = "bepdf:page_num";

static GBool printHelp = gFalse;
// GBool printCommands = gFalse;

static ArgDesc argDesc[] = {
	{"-z", argIntDummy, NULL, 0,
	 "initial zoom level (-5..5)"},
	{"-ps", argStringDummy, NULL, 0,
	 "default PostScript file/command name"},
	{"-cmd", argFlag, &printCommands, 0,
	 "print commands as they're executed"},
	{"-h", argFlag, &printHelp, 0,
	 "print usage information"},
	{NULL}
};

unsigned char pointer_cursor[] = 
{16, // width & hight
1, // color depth
8, 8, // hotspot coordinates
// color data (32 bytes)
0x07, 0xE0, 0x18, 0x18, 0x20, 0x04, 0x70, 0x0E,
0x78, 0x1E, 0xFC, 0x3F, 0xFE, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0x7F, 0xFC, 0x3F, 0x78, 0x1E,
0x70, 0x0E, 0x20, 0x04, 0x18, 0x18, 0x07, 0xE0,
// transparency bitmask (32 bytes)
0x07, 0xE0,0x1F, 0xF8,0x3F, 0xFC,0x7F, 0xFE,
0x7F, 0xFE,0xFF, 0xFF,0xFF, 0xFF,0xFF, 0xFF,
0xFF, 0xFF,0xFF, 0xFF,0xFF, 0xFF,0x7F, 0xFE,
0x7F, 0xFE,0x3F, 0xFC,0x1F, 0xF8,0x07, 0xE0
};        

unsigned char link_cursor[] =
{16, // width & hight
1, // color depth
8, 8, // hotspot coordinates
// color data (32 bytes)
0x07, 0xE0, 0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE,
0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE,
0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, 0x07, 0xE0,
// transparency bitmask (32 bytes)
0x07, 0xE0,0x1F, 0xF8,0x3F, 0xFC,0x7F, 0xFE,
0x7F, 0xFE,0xFF, 0xFF,0xFF, 0xFF,0xFF, 0xFF,
0xFF, 0xFF,0xFF, 0xFF,0xFF, 0xFF,0x7F, 0xFE,
0x7F, 0xFE,0x3F, 0xFC,0x1F, 0xF8,0x07, 0xE0
};    

unsigned char hand_cursor[] = 
{16, // width & hight
1, // color depth
8, 8, // hotspot coordinates
// color data (32 bytes)
0x01, 0x80, 0x1A, 0x70, 0x26, 0x48, 0x26, 0x4A,
0x12, 0x4D, 0x12, 0x49, 0x68, 0x09, 0x98, 0x01,
0x88, 0x02, 0x40, 0x02, 0x20, 0x02, 0x20, 0x04,
0x10, 0x04, 0x08, 0x08, 0x04, 0x08, 0x04, 0x08,
// transparency bitmask (32 bytes)
0x01, 0x80,0x1B, 0xF0,0x3F, 0xF8,0x3F, 0xFA,
0x1F, 0xFF,0x1F, 0xFF,0x6F, 0xFF,0xFF, 0xFF,
0xFF, 0xFE,0x7F, 0xFE,0x3F, 0xFE,0x3F, 0xFC,
0x1F, 0xFC,0x0F, 0xF8,0x07, 0xF8,0x07, 0xF8
};        

unsigned char grab_cursor[] =
{16, // width & hight
1, // color depth
9, 9, // hotspot coordinates
// color data (32 bytes)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0D, 0xB0, 0x12, 0x4C, 0x10, 0x0A, 0x08, 0x02,
0x18, 0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x04,
0x10, 0x04, 0x08, 0x08, 0x04, 0x08, 0x04, 0x08,
// transparency bitmask (32 bytes)
0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,
0x0D, 0xB0,0x1F, 0xFC,0x1F, 0xFE,0x0F, 0xFE,
0x1F, 0xFE,0x3F, 0xFE,0x3F, 0xFE,0x3F, 0xFC,
0x1F, 0xFC,0x0F, 0xF8,0x07, 0xF8,0x07, 0xF8 
};    

///////////////////////////////////////////////////////////
int main()
{
#if HAVE_T1LIB_H
  /* Set our environment to an existent config file directory */
  putenv( "T1LIB_CONFIG=./t1lib.config");

  /* Pad bitmaps to 16 bits, the default being 8 bits */
  T1_SetBitmapPad( 8);
  /* Initialize t1lib and return if error occurs. No logfile will be
     generated */
  if ((T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE |
		   T1_NO_AFM)==NULL)){
    fprintf(stderr, "Initialization of t1lib failed\n");
    return(-1);
  }
  T1_AASetBitsPerPixel(8);
  T1_AASetGrayValues(0, 64, 128, 192, 255); 
  
  unsigned long grayValues[17];
  for (int i = 0; i <= 16; i++) {
  	grayValues[i] = 63 + i * 192 / 16;
  }
  grayValues[0] = 0;
  T1_AAHSetGrayValues(grayValues);
  T1_AASetLevel(T1_AA_HIGH);
#endif
	new BepdfApplication ( );
	
	be_app->Run();
	
	delete be_app;
	
#if HAVE_T1LIB_H
  /* Close library and free all data */
  T1_CloseLib();
#endif	
	return 0;
}



///////////////////////////////////////////////////////////
BepdfApplication::BepdfApplication()
		: BApplication ( "application/x-vnd.mp-xpdf" )
{
	mOpenFilePanel = NULL;
	mGotSomething = false;
#ifdef SINGLE_DOCUMENT_VIEW
	mWindow = NULL;
#endif	
	errorInit ();
	initParams (xpdfConfigFile);
	// pointerCursor = new BCursor(pointer_cursor);
	pointerCursor = (BCursor*)B_CURSOR_SYSTEM_DEFAULT; //new BCursor(pointer_cursor);
	linkCursor = (BCursor*)B_CURSOR_SYSTEM_DEFAULT; //new BCursor(link_cursor);
	handCursor = new BCursor(hand_cursor);
	grabCursor = new BCursor(grab_cursor);
}


///////////////////////////////////////////////////////////
BepdfApplication::~BepdfApplication()
{
	freeParams();

	// check for memory leaks
	Object::memCheck(errFile);
	gMemReport(errFile);

	// print coverage info
	//coverDump(errFile);
	// if (pointerCursor != NULL) delete pointerCursor;
	// if (linkCursor != NULL) delete linkCursor;
	if (handCursor != NULL) delete handCursor;
	if (grabCursor != NULL) delete grabCursor;
}


///////////////////////////////////////////////////////////
void BepdfApplication::ReadyToRun()
{
	if (! mGotSomething) {
		OpenFilePanel();
	}
}

///////////////////////////////////////////////////////////
void BepdfApplication::AboutRequested()
{
	BString str("PDFViewer version ");
	str += pdfViewerVersion;
	str += "\nbased on xpdf ";
	str += xpdfVersion;
	str += "\n";
	str += xpdfCopyright;
	str += "\nand based on BePDF ";
	str += bePDFVersion;
	str += "\n";
	str += bePDFCopyright;
	str += "\n";
	str += pdfViewerCopyright;
	BAlert *about = new BAlert("About", str.String(), "Ok");
	about->Go();
}


/*
	open a file panel and ask for a PDF file 
	the file panel will tell by itself if openning have been cancelled 
	or not.
*/
void BepdfApplication::OpenFilePanel ()
{
	if (mOpenFilePanel == NULL) {
		mOpenFilePanel = new BFilePanel (B_OPEN_PANEL,
						NULL, NULL, B_FILE_NODE, true, NULL, NULL);
	}
	
	mOpenFilePanel->Show();
}


		

///////////////////////////////////////////////////////////
/*
	Opens everything.
*/
void BepdfApplication::RefsReceived ( BMessage * msg )
{
	uint32 type;
	int32 count;
	int32 i;
	entry_ref ref;
	
	msg->GetInfo ( "refs", &type, &count );
	if ( type != B_REF_TYPE ) {
		return;
	}
	for ( i = --count ; i >= 0; i-- ) {
		BScreen screen;
		if ( msg->FindRef("refs", i, &ref ) == B_OK ) {
			/*
				Open the document...
			*/
			PDFWindow *win;
#ifdef SINGLE_DOCUMENT_VIEW
			StatusWindow * status;
			if (mWindow == NULL) {
				status = new StatusWindow(ref.name, screen.Frame());
				win = new PDFWindow(&ref, BRect(100, 30, 200, 250));
				mWindow = win;
			} else {
				status = new StatusWindow(ref.name, mWindow->Frame());
				win = mWindow;
				mWindow->LoadFile(&ref);
			} 
#else // multiple document view
			StatusWindow * status = new StatusWindow(ref.name, screen.Frame());
			PDFWindow * win = new PDFWindow(&ref, BRect(100, 30, 200, 250));
#endif
		 	status->PostMessage(B_QUIT_REQUESTED);
		 	if (! win->IsOk()) {
#ifdef DEBUG
		 		fprintf (stderr, "Window not created");
#endif
		 		delete win;
		 		BAlert *error = new BAlert("Error", "PDFViewer: Error opening file!", "Close", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
		 		error->Go();
		 	}
	 		else {
	 			win->Show();
	 			mGotSomething = true;
#ifdef SINGLE_DOCUMENT_VIEW
				// stop after first document
				return;
#endif
		 	}
		} 
	}
}



///////////////////////////////////////////////////////////
void
BepdfApplication::MessageReceived (BMessage * msg)
{
	if (msg == NULL) {
		fprintf (stderr, "xpdf: message NULL received\n");
		return;
	}
	switch (msg->what) {
	case B_CANCEL:
		if (PDFWindow::GetWindowCount() == 0) {
			PostMessage (B_QUIT_REQUESTED);
		}
		break;
	}
}





///////////////////////////////////////////////////////////
void
BepdfApplication::ArgvReceived (int32 argc, char **argv)
{
	GString * name;
	GBool ok;
	int pg;
	entry_ref fileToOpen;
	
	ok = parseArgs (argDesc, (int *)&argc, argv);
	
	// check command line
	if (!(argc == 2 || argc == 3) || printHelp) {
		printUsage(argv[0], "[<PDF-file> [<page>]]", argDesc);
		exit(1);
	}
	if (argc >= 2) {
		name = new GString(argv[1]);
	}
	else {
		name = NULL;
	}
	if (argc == 3) {
		pg = atoi(argv[2]);
	}
	else {
		pg = 1;
	}

	// print banner
	fprintf(errFile, "PDFViewer version %s\n", pdfViewerVersion);
	fprintf(errFile, "based on xpdf %s %s\n", xpdfVersion, xpdfCopyright);
	fprintf(errFile, "and based on BePDF %s\n%s\n", bePDFVersion, bePDFCopyright);
	fprintf(errFile, "%s\n", pdfViewerCopyright);

	BMessage msg(B_REFS_RECEIVED);
	msg.AddInt32 (PAGE_NUM_MSG, pg);
	get_ref_for_path (name->getCString(), &fileToOpen);
	msg.AddRef ("refs", &fileToOpen);
	PostMessage (&msg);
	mGotSomething = true;
}


///////////////////////////////////////////////////////////
