/*******************************************************************************

  Copyright(c) 2003-2004 Aurelien Reynaud.

  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., 59
  Temple Place - Suite 330, Boston, MA  02111-1307, USA.

  The full GNU General Public License is included in this distribution in the
  file called COPYING.

*******************************************************************************/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "ggiterm.h"
#include "debug.h"

#include <ggi/ggi.h>

/* External variables */
extern ggi_visual_t vis;

/* Global variables */
int cell_w, cell_h;
ggi_visual_t backend_vis;
void (*backend_real_exit)();

/* External functions */
int   cache_init(long box_size);
void* cache_get(wchar_t charcode, int fgcol, int bgcol, int underline);
void  cache_exit();
int native_init(int*, int*);
void native_exit();
#ifdef HAVE_FREETYPE
int freetype_init(char*, int, int*, int*);
void freetype_exit();
#endif /* HAVE_FREETYPE */


int backend_visual_init(int width, int height)
{
	ggi_mode current_mode;
	long pixelbuf_size;
	const ggi_pixelformat *mypixelformat;
	int err;
	
	debug(DEBUG_FUNCTION,
	      "called with args (width=%d, height=%d", width, height);

	ggiGetMode(vis, &current_mode);
	debug(DEBUG_INIT, "Opening memory visual for glyph caching");
	backend_vis = ggiOpen("display-memory", NULL);
	if (backend_vis == NULL) {
		error("Couldn't open memory visual!");
		debug(DEBUG_FUNCTION, "Leaving");
		return 1;
	}
	err = ggiSetSimpleMode(backend_vis, width, height, 1, current_mode.graphtype);
	if (err) {
		error("Cannot set mode");
		ggiClose(backend_vis);
		debug(DEBUG_FUNCTION, "Leaving");
		return 1;
	}
	
	mypixelformat = ggiGetPixelFormat(backend_vis);
	
	pixelbuf_size = (mypixelformat->size * width * height + 7)/8;
	err = cache_init(pixelbuf_size);
	if (err) {
		error("Could not allocate cache");
		ggiClose(backend_vis);
		debug(DEBUG_FUNCTION, "Leaving");
		return 1;
	}
	return 0;
}

void backend_visual_exit()
{
	cache_exit();
	ggiClose(backend_vis);
}

int backend_write_char(int x, int y, wchar_t charcode, int fgcolor, int bgcolor, int underline)
{
	int err;
	void *boxptr;

	debug(DEBUG_FUNCTION,
	      "called with args (x=%d, y=%d, charcode=0x%X, fgcolor=%d, bgcolor=%d, underline=%d",
	      x, y, (int)charcode, fgcolor, bgcolor, underline);
	
	boxptr = cache_get(charcode, fgcolor, bgcolor, underline);
	if (boxptr != NULL) {
		err = ggiPutBox(vis, x, y, cell_w, cell_h, boxptr);
		if (err) {
			error("PutBox failed");
			debug(DEBUG_FUNCTION, "Leaving");
			return 1;
		}
	}

	debug(DEBUG_FUNCTION, "Leaving");
	return 0;
}

/*
 * Determines and initializes the best possible backend
 * Fills in cell_h, cell_w and backend_write_char
 * Returns 0 on error, 1 for native backend, 2 for freetype backend
 */
int backend_init(char *font_file, int fontsize, int *backend_w, int *backend_h)
{
	int backend = BACKEND_ERROR;
	int err;

	debug(DEBUG_FUNCTION,
	      "called with args (font_file=%s, fontsize=%d, *backend_w, *backend_h)",
	      font_file, fontsize);
	if (font_file != NULL) {
#ifdef HAVE_FREETYPE
		debug(DEBUG_INIT, "Trying Freetype backend");
		if (!freetype_init(font_file, fontsize, &cell_w, &cell_h)) {
			debug(DEBUG_INIT, "Using Freetype backend");
			backend = BACKEND_FREETYPE;
			backend_real_exit = &freetype_exit;
		}
#else /* HAVE_FREETYPE */
		error("Freetype support not compiled in");
#endif /* HAVE_FREETYPE */
		if (!backend) {
			debug(DEBUG_INIT, "Cannot use Freetype backend");
			if (!native_init(&cell_w, &cell_h)) {
				error("Falling back to native GGI "
		 	 	      "backend (ASCII only)");
				backend = BACKEND_NATIVE;
				backend_real_exit = &native_exit;
			}
		}
	} else {
		debug(DEBUG_INIT, "No font file provided");
		if (!native_init(&cell_w, &cell_h)) {
			debug(DEBUG_INIT,
			      "Using native GGI backend (ASCII only)");
			backend = BACKEND_NATIVE;
			backend_real_exit = &native_exit;
		}
	}

	if (backend != BACKEND_ERROR) {
		err = backend_visual_init(cell_w, cell_h);
		if (err) {
			error("Couldn't initialize glyph cache");
			backend_real_exit();
			backend = BACKEND_ERROR;
		}
	}

	*backend_w = cell_w;
	*backend_h = cell_h;

	debug(DEBUG_FUNCTION, "Leaving");
	return backend;
}

void backend_exit()
{
	debug(DEBUG_FUNCTION, "called with no args");
	debug(DEBUG_INIT, "Freeing glyph visual");
	backend_visual_exit();
	debug(DEBUG_INIT, "Calling real backend's _exit()");
	backend_real_exit();	
	debug(DEBUG_FUNCTION, "Leaving");
}
