[SCM] Development fot GoFind! branch, master, updated. 8eb067988ba21988e57f90e0fa3fb1dccb314fdb

Miriam Ruiz miriam at debian.org
Sun Nov 23 03:02:08 UTC 2008


The following commit has been merged in the master branch:
commit 8eb067988ba21988e57f90e0fa3fb1dccb314fdb
Author: Miriam Ruiz <miriam at debian.org>
Date:   Sun Nov 23 02:01:36 2008 +0100

    Add skeleton for FLTK plugin

diff --git a/Makefile b/Makefile
index 74ff962..9abc058 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ OBJS= Engine.o Environment.o filter.o field.o gofind.o \
 	taghandler.o cfgmanager.o boolparser.o \
 	utf8.o dll.o guiplugin.o
 
-PLUGINS= gui_cli.so
+PLUGINS= gui_cli.so gui_fltk.so
 
 all: gofind $(PLUGINS)
 
@@ -48,6 +48,12 @@ gui_cli.so: gui_cli.o slre.o
 %.so : %.o
 	g++ $(CFLAGS) -shared $^ -o $@
 
+gui_fltk.so : fltk/ui.h gui_fltk.o fltk/aux.o fltk/windows.o fltk/pkgbrowser.o fltk/ui.o
+	g++ $(LDFLAGS) -shared $^ -o $@ `fltk-config --ldflags --use-images` $(LIBS)
+
+fltk/ui.h fltk/ui.cpp: fltk/ui.fld
+	cd fltk && fluid -c -o ui.cpp -h ui.h ui.fld
+
 TEST_OBJS=  filter.test.o taghandler.test.o cfgmanager.test.o boolparser.test.o slre.test.o utf8.test.o CuTest.o dll.test.o test.o
 TEST_PLUGINS= testplugin.test.so
 
@@ -70,4 +76,4 @@ test.o: test.c
 	g++ $(CFLAGS)  -DUNIT_TEST -shared $^ -o $@
 
 clean:
-	rm -f gofind test test.c *.o *.so
+	rm -f gofind test test.c cli/*.o fltk/*.o *.o *.so
diff --git a/data/html/about.en.html b/data/html/about.en.html
new file mode 100644
index 0000000..95b84d4
--- /dev/null
+++ b/data/html/about.en.html
@@ -0,0 +1,18 @@
+<center><h1>GoPlay!</h1></center><br />
+<br />&nbsp;<br />
+Copyright (C) 2007  <a href="mailto:little_miry at yahoo.es">Miriam Ruiz</a><br />
+Copyright (C) 2007  <a href="mailto:enrico at debian.org">Enrico Zini</a><br />
+<br />&nbsp;<br />
+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.
+<br />&nbsp;<br />
+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.
+<br />&nbsp;<br />
+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
diff --git a/data/icons/Icon32.png b/data/icons/Icon32.png
new file mode 100644
index 0000000..6e6bedd
Binary files /dev/null and b/data/icons/Icon32.png differ
diff --git a/data/icons/Icon64.png b/data/icons/Icon64.png
new file mode 100644
index 0000000..bf2828f
Binary files /dev/null and b/data/icons/Icon64.png differ
diff --git a/data/icons/Rating.png b/data/icons/Rating.png
new file mode 100644
index 0000000..4f38324
Binary files /dev/null and b/data/icons/Rating.png differ
diff --git a/data/icons/Rating.xcf b/data/icons/Rating.xcf
new file mode 100644
index 0000000..9e60df1
Binary files /dev/null and b/data/icons/Rating.xcf differ
diff --git a/data/no_screenshot.alpha.png b/data/no_screenshot.alpha.png
new file mode 100644
index 0000000..7b1ad5f
Binary files /dev/null and b/data/no_screenshot.alpha.png differ
diff --git a/data/no_screenshot.png b/data/no_screenshot.png
new file mode 100644
index 0000000..61d7691
Binary files /dev/null and b/data/no_screenshot.png differ
diff --git a/data/people.png b/data/people.png
new file mode 100644
index 0000000..37a7aa8
Binary files /dev/null and b/data/people.png differ
diff --git a/data/people_off.png b/data/people_off.png
new file mode 100644
index 0000000..c312964
Binary files /dev/null and b/data/people_off.png differ
diff --git a/data/people_on.png b/data/people_on.png
new file mode 100644
index 0000000..2b43067
Binary files /dev/null and b/data/people_on.png differ
diff --git a/data/stars_border.big.png b/data/stars_border.big.png
new file mode 100644
index 0000000..650458c
Binary files /dev/null and b/data/stars_border.big.png differ
diff --git a/data/stars_filled.big.png b/data/stars_filled.big.png
new file mode 100644
index 0000000..27b0553
Binary files /dev/null and b/data/stars_filled.big.png differ
diff --git a/data/stars_off.alpha.png b/data/stars_off.alpha.png
new file mode 100644
index 0000000..d398ea7
Binary files /dev/null and b/data/stars_off.alpha.png differ
diff --git a/data/stars_off.big.png b/data/stars_off.big.png
new file mode 100644
index 0000000..cf22bdf
Binary files /dev/null and b/data/stars_off.big.png differ
diff --git a/data/stars_off.png b/data/stars_off.png
new file mode 100644
index 0000000..63a76ec
Binary files /dev/null and b/data/stars_off.png differ
diff --git a/data/stars_on.alpha.png b/data/stars_on.alpha.png
new file mode 100644
index 0000000..2d703cd
Binary files /dev/null and b/data/stars_on.alpha.png differ
diff --git a/data/stars_on.big.png b/data/stars_on.big.png
new file mode 100644
index 0000000..8a657ff
Binary files /dev/null and b/data/stars_on.big.png differ
diff --git a/data/stars_on.png b/data/stars_on.png
new file mode 100644
index 0000000..8b2ccf3
Binary files /dev/null and b/data/stars_on.png differ
diff --git a/fltk/aux.cpp b/fltk/aux.cpp
new file mode 100644
index 0000000..275290d
--- /dev/null
+++ b/fltk/aux.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2007  Miriam Ruiz <little_miry at yahoo.es>
+ *
+ * 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
+ */
+
+#include "aux.h"
+#include "../common.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <string>
+
+#include <FL/Fl.H>
+#include <FL/Fl_Help_View.H>
+
+bool HTMLView::ExternalBrowser(const char *uri)
+{
+	pid_t pid = -1;
+	if ((pid=fork()) == -1)
+	{
+		ERROR_PRINTF("fork: %s\n", strerror(errno));
+		return false;
+	}
+
+	if (strchr(uri, '"')) return false; /* No "s allowed in the uri for the moment */
+
+	if (pid) /* A positive (non-negative) PID indicates the parent process */
+		return true;
+
+	/* A zero PID indicates that this is the child process */
+	std::string command = std::string("/usr/bin/x-www-browser \"") + uri +"\"";
+	if (execl("/bin/sh", "sh", "-c", command.c_str(), (char *) 0) == -1)
+		ERROR_PRINTF("exec: %s\n", strerror(errno));
+
+	exit(1); /* This point should never be reached */
+}
+
+HTMLView::HTMLView(int xx, int yy, int ww, int hh, const char *l) : Fl_Help_View(xx, yy, ww, hh, l), draw_cb(NULL)
+{
+	link(HTMLView::link_cb);
+}
+
+HTMLView::~HTMLView()
+{
+}
+
+const char *HTMLView::link_cb(Fl_Widget *w, const char *uri)
+{
+	HTMLView *html_view = (HTMLView *)w;
+	printf("PackageView::link_cb(): Widget=0x%lX, URI=\"%s\"\n", (unsigned long)w, uri);
+
+	if (html_view->draw_cb) html_view->draw_cb(html_view);
+
+	if (!strncasecmp("http:", uri, 5) || !strncasecmp("ftp:", uri, 4) || !strncasecmp("https:", uri, 6))
+	{
+		HTMLView::ExternalBrowser(uri);
+		return NULL;
+	}
+
+	if (!strncasecmp("mailto:", uri, 7))
+	{
+		return NULL;
+	}
+
+		if (!strncasecmp("pkg:", uri, 4))
+	{
+		return NULL;
+	}
+
+	return uri;
+}
diff --git a/cfgmanager.h b/fltk/aux.h
similarity index 57%
copy from cfgmanager.h
copy to fltk/aux.h
index 8c6d57a..0b3f71f 100644
--- a/cfgmanager.h
+++ b/fltk/aux.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008  Miriam Ruiz <little_miry at yahoo.es>
+ * Copyright (C) 2007  Miriam Ruiz <little_miry at yahoo.es>
  *
  * 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
@@ -16,23 +16,27 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef _GOFIND_CONFIGMANAGER_H
-#define _GOFIND_CONFIGMANAGER_H
+#ifndef _GOFIND_FLTK_AUX_H
+#define _GOFIND_FLTK_AUX_H
 
-class ConfigManager
+#include <FL/Fl.H>
+#include <FL/Fl_Help_View.H>
+
+class HTMLView : public Fl_Help_View
 {
 public:
-    /**
-        Initializes the configuration manager.
-    */
-    ConfigManager();
+	HTMLView(int xx, int yy, int ww, int hh, const char *l = 0);
+	~HTMLView();
+
+	static bool ExternalBrowser(const char *uri);
 
-    /**
-        Destroys the configuration manager and frees the associated resources.
-    */
-    ~ConfigManager();
+	typedef void DrawCallback(HTMLView *html_view);
+	inline void SetDrawCallback(DrawCallback *function) { draw_cb = function;}
 
 private:
+	static const char *link_cb(Fl_Widget *w, const char *uri);
+
+	DrawCallback *draw_cb;
 };
 
-#endif // _GOFIND_CONFIGMANAGER_H
+#endif // _GOFIND_FLTK_AUX_H
diff --git a/fltk/pkgbrowser.cpp b/fltk/pkgbrowser.cpp
new file mode 100644
index 0000000..c7aa245
--- /dev/null
+++ b/fltk/pkgbrowser.cpp
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2007, 2008  Miriam Ruiz <little_miry at yahoo.es>
+ *
+ * VersatileBrowser uses ColResizeBrowser, written by Greg Ercolano
+ * ColResizeBrowser (C) Greg Ercolano <erco at seriss.com>
+ * URL: http://seriss.com/people/erco/fltk/
+ * GNU GPL License (version 2 or, at your option, any later version)
+ *
+ * PackageBrowser::item_draw and PackageBrowser::item_width
+ * use code from FLTK 1.1 Fl_Browser.cxx
+ * Browser widget for the Fast Light Tool Kit (FLTK).
+ * Copyright 1998-2005 by Bill Spitzak and others.
+ * URL: http://www.fltk.org/
+ * GNU LGPL License (version 2 or, at your option, any later version)
+ *
+ * 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
+ */
+
+#include "pkgbrowser.h"
+#include "ui.h"
+#include "aux.h"
+#include "../common.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <string>
+#include <limits.h>
+#include <sys/stat.h>
+
+#include <ept/apt/apt.h>
+#include <ept/debtags/debtags.h>
+#include <ept/textsearch/textsearch.h>
+#include <ept/debtags/tag.h>
+#include <ept/apt/packagerecord.h>
+#include <ept/popcon/popcon.h>
+#include <string>
+#include <set>
+#include <vector>
+
+#ifdef USE_GETTEXT
+#include <libintl.h>
+#include <locale.h>
+#else
+// Work-around until goplay is actually gettextised
+#define gettext(a) (a)
+#endif
+
+#include <FL/Fl_PNG_Image.H>
+#include <FL/Fl_JPEG_Image.H>
+#include <FL/Fl_BMP_Image.H>
+
+using namespace std;
+using namespace ept;
+using namespace ept::debtags;
+using namespace ept::apt;
+
+static const char legalchars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz at _?+-,.~/%&=:*#";
+
+PackageBrowser::PackageBrowser(int x, int y, int w, int h, const char *l)
+	: VersatileBrowser(x, y, w, h, l), num_bar_images(2)
+{
+	showcolsep(1);
+	//colsepcolor(FL_RED);
+	column_char('\t'); // tabs as column delimiters
+	bar_images[0] = new Fl_PNG_Image(FILE_STARS_ON);
+	bar_images[1] = new Fl_PNG_Image(FILE_STARS_OFF);
+	bar_images[2] = new Fl_PNG_Image(FILE_PEOPLE_ON);
+	bar_images[3] = new Fl_PNG_Image(FILE_PEOPLE_OFF);
+	for (unsigned int i = 0; i < num_bar_images*2; i++)
+	{
+		if (bar_images[i] && !bar_images[i]->count())
+			printf(_("Invalid bar image %u\n"), i);
+	}
+}
+
+PackageBrowser::~PackageBrowser()
+{
+	for (unsigned int i = 0; i < num_bar_images*2; i++)
+	{
+		if (bar_images[i]) delete bar_images[i];
+	}
+}
+
+static void text2html(const std::string &in_text, std::string &out_html)
+{
+	const char *text = in_text.c_str();
+	const char *src = text;
+	//out_html.erase();
+	while (*src)
+	{
+		if (!strncasecmp("http:", src, 5) || !strncasecmp("mailto:", src, 7) ||
+			!strncasecmp("ftp:", src, 4) || !strncasecmp("https:", src, 6))
+		{
+			std::string uri, uri_text;
+			for (; *src && (strchr(legalchars, *src) || (*src & 128)); src++)
+			{
+				uri += *src;
+				uri_text += *src;
+				if (*src == '/')
+					uri_text += "<wbr>";
+			}
+			if (strchr(".?!", src[-1])) {  // Probably the end of a sentence
+				--src;
+				uri.resize(uri.size() - 1);
+				uri_text.resize(uri_text.size() - 1);
+			}
+			out_html += "<a href=\"";
+			out_html += uri;
+			out_html += "\">";
+			out_html += uri_text;
+			out_html += "</a>";
+		}
+		else if (!strncasecmp(" .\n", src, 3))
+		{
+			out_html += "<br />&nbsp;<br />";
+			src += 2;
+		}
+		else if (*src <= ' ')
+		{
+			out_html += " ";
+			src++;
+		}
+		else
+		{
+			switch(*src)
+			{
+				case '<': out_html += "&lt;"; break;
+				case '>': out_html += "&gt;"; break;
+				default:
+				out_html += *src;
+			}
+			src++;
+		}
+	}
+}
+
+void PackageBrowser::item_select(void *p, int s)
+{
+	VersatileBrowser::item_select(p, s);
+
+	if (s)
+	{
+		int n = VersatileBrowser::lineno(p);
+		void *data = VersatileBrowser::data(n);
+		//printf("  #%d : \"%s\"\n", n, (const char *)data);
+		//fflush(stdout);
+
+		if (data)
+		{
+			char filename[PATH_MAX];
+			struct stat fileinfo;
+			Fl_Image *img = NULL;
+			if (snprintf(filename, PATH_MAX, "%s/%s.png", THUMBNAILSDIR, (const char *)data) &&
+				stat(filename, &fileinfo) == 0)
+			{ // Portable Network Graphics (PNG) image files
+				// We were able to get the file attributes so the file obviously exists.
+				img = new Fl_PNG_Image(filename);
+				//printf("  PNG Screenshot : \"%s\"\n", filename);
+			}
+			else if (snprintf(filename, PATH_MAX, "%s/%s.jpg", THUMBNAILSDIR, (const char *)data) &&
+				stat(filename, &fileinfo) == 0)
+			{ // Joint Photographic Experts Group (JPEG) File Interchange Format (JFIF) images.
+				img = new Fl_JPEG_Image(filename);
+				//printf("  JPEG Screenshot : \"%s\"\n", filename);
+			}
+			else if (snprintf(filename, PATH_MAX, "%s/%s.jpeg", THUMBNAILSDIR, (const char *)data) &&
+				stat(filename, &fileinfo) == 0)
+			{
+				img = new Fl_JPEG_Image(filename);
+				//printf("  JPEG Screenshot : \"%s\"\n", filename);
+			}
+			else if (snprintf(filename, PATH_MAX, "%s/%s.bmp", THUMBNAILSDIR, (const char *)data) &&
+				stat(filename, &fileinfo) == 0)
+			{ // Windows Bitmap (BMP) image files
+				img = new Fl_BMP_Image(filename);
+				//printf("  BMP Screenshot : \"%s\"\n", filename);
+			}
+			else
+			{ // TODO: Portable Anymap (PNM, PBM, PGM, PPM) image files
+				img = NULL;
+			}
+			if (img && !img->count())
+			{
+				printf("  Wrong Screenshot.\n");
+				delete img;
+				img = NULL;
+			}
+			if (!img)
+			{
+				strncpy(filename, FILE_NO_SCREENSHOT, PATH_MAX);
+				img = new Fl_PNG_Image(FILE_NO_SCREENSHOT);
+			}
+
+			Fl_Group *highest_parent=parent();
+			while (highest_parent->parent()) highest_parent = highest_parent->parent();
+			GamesUI *ui = highest_parent ? (GamesUI*)(highest_parent->user_data()) : NULL;
+			if (ui && img) ui->Screenshot(img);
+
+			const char *pkgname = "package";
+			const char *pkgshort = "package short description";
+			const char *pkglong ="Lorem ipsum dolor sit amet, "
+				"consectetur adipiscing elit, sed eiusmod tempor incidunt ut labore "
+				"et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
+				"exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. "
+				"Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu "
+				"fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, "
+				"sunt in culpa qui officia deserunt mollit anim id est laborum.";
+
+			std::string pkg_desc;
+			if (ui)
+			{
+				pkg_desc = std::string ("<center><h1><a href=\"pkg:")
+					+ pkgname + "\">" + pkgname + "</a></h1></center><br />";
+				pkg_desc += std::string("<center>") + pkgshort + "</center><hr /><p>";
+				text2html(pkglong, pkg_desc);
+				ui->InfoView->value(pkg_desc.c_str());
+			}
+
+			static int widths[] = { 150, 0 }; // widths for each column
+			ui->DebTagsBrowser->clear();
+			ui->DebTagsBrowser->showcolsep(1);
+			ui->DebTagsBrowser->column_widths(widths);
+			ui->DebTagsBrowser->add(_("@B12 at C7@b at .FACET\t at B12@C7 at b@.TAG"));
+/*
+			const char taglist[][32] = {
+				"example::tag1" ,
+				"example::tag2" ,
+				"example::tag3" ,
+				"example::tag4" ,
+				"example::tag5"
+			};
+*/
+			ept::debtags::Debtags debtags;
+
+			set<ept::debtags::Tag> tags = debtags.getTagsOfItem("libc6");
+			char *tag_txt = new char[512];
+			for (set<ept::debtags::Tag>::const_iterator i = tags.begin(); i != tags.end(); ++i)
+			{
+				// Available Colors: FL_BLACK, FL_BLUE, FL_CYAN, FL_DARK_BLUE,
+				// FL_DARK_CYAN, FL_DARK_GREEN FL_DARK_MAGENTA, FL_DARK_RED,
+				// FL_DARK_YELLOW, FL_GREEN, FL_MAGENTA, FL_RED, FL_WHITE, FL_YELLOW
+
+				Fl_Color bk(FL_WHITE);
+				Fl_Color fr(FL_BLACK);
+/*
+				switch (pkgfilter.TagValue(*i))
+				{
+					case PackageFilter::Green:
+						fr = FL_BLACK; bk = FL_GREEN; break;
+					case PackageFilter::Yellow:
+						fr = FL_BLACK; bk = FL_YELLOW; break;
+					case PackageFilter::Red:
+						fr = FL_WHITE; bk = FL_RED; break;
+					case PackageFilter::Black:
+						fr = FL_WHITE; bk = FL_BLACK; break;
+					default:
+						fr = FL_BLACK; bk = FL_WHITE; break;
+				}
+*/
+				snprintf(tag_txt, 512, "@B%d at C%d at .%s\t at B%d at C%d at .%s",
+					bk, fr,
+					gettext(i->facet().shortDescription().c_str()),
+					bk, fr,
+					gettext(i->shortDescription().c_str())
+				);
+				ui->DebTagsBrowser->add(tag_txt);
+			}
+			delete [] tag_txt;
+		}
+
+		fflush(stdout);
+	}
+}
+
+int PackageBrowser::item_width(void *p) const
+{
+	int n = VersatileBrowser::lineno(p);
+	char *text = strdup(VersatileBrowser::text(n));
+	char *str = text;
+	const int* i = column_widths();
+	int ww = 0;
+
+	while (*i)
+	{ // add up all tab-seperated fields
+		char* e;
+		e = strchr(str, column_char());
+		if (!e) break; // last one occupied by text
+		str = e+1;
+		ww += *i++;
+	}
+
+	// OK, we gotta parse the string and find the string width...
+	int tsize = textsize();
+	Fl_Font font = textfont();
+	int done = 0;
+
+	while (*str == format_char() && str[1] && str[1] != format_char())
+	{
+		str ++;
+		switch (*str++)
+		{
+			case 'l': case 'L': tsize = 24; break;
+			case 'm': case 'M': tsize = 18; break;
+			case 's': tsize = 11; break;
+			case 'b': font = (Fl_Font)(font|FL_BOLD); break;
+			case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
+			case 'f': case 't': font = FL_COURIER; break;
+			case 'B':
+			case 'C': strtol(str, &str, 10); break;// skip a color number
+			case 'F': font = (Fl_Font)strtol(str, &str, 10); break;
+			case 'S': tsize = strtol(str, &str, 10); break;
+			case '.': done = 1; break;
+			case '@': str--; done = 1;
+		}
+		if (done) break;
+	}
+
+	int last_w = 0;
+	if (*str=='%' && '0'<=str[1] && str[1]<='9')
+	{
+		char *after;
+		/* int percent = */ strtol(str+1, &after, 10);
+		int steps = 0;
+		unsigned int bar = 0;
+		if (after && *after=='/')
+			steps = strtol(after+1, &after, 10);
+		if (steps < 0 ) steps = 100;
+		if (after && *after=='/')
+			bar = strtol(after+1, &after, 10);
+		if (bar >= num_bar_images ) bar = num_bar_images - 1;
+		if (bar < 0 ) bar = 0;
+
+		if (bar_images[bar*2] && bar_images[bar*2]->w() > last_w) last_w = bar_images[bar*2]->w();
+		if (bar_images[bar*2+1] && bar_images[bar*2+1]->w() > last_w) last_w = bar_images[bar*2+1]->w();
+	}
+	else
+	{
+		if (*str == format_char() && str[1]) str ++;
+		fl_font(font, tsize);
+		last_w = int(fl_width(str));
+	}
+
+	free (text);
+	return ww + last_w + 6;
+}
+
+void PackageBrowser::item_draw(void *p, int x, int y, int w, int h) const
+{
+	//printf("PackageBrowser::item_draw(p=0x%lX, x=%d, y=%d, w=%d, h=%d)\n", (unsigned long)p, x, y, w, h);
+	int n = VersatileBrowser::lineno(p);
+	//void *data = VersatileBrowser::data(n);
+	//printf("   data=\"%s\"\n", (char *)data);
+	char *text = strdup(VersatileBrowser::text(n));
+	char *str = text;
+	const int* i = column_widths();
+
+	while (w > 6)
+	{	// do each tab-seperated field
+		int w1 = w;	// width for this field
+		char* e = 0; // pointer to end of field or null if none
+		if (*i)
+		{ // find end of field and temporarily replace with 0
+			e = strchr(str, column_char());
+			if (e) {*e = 0; w1 = *i++;}
+		}
+		int tsize = textsize();
+		Fl_Font font = textfont();
+		Fl_Color lcol = textcolor();
+		Fl_Align talign = FL_ALIGN_LEFT;
+		// check for all the @-lines recognized by XForms:
+		while (*str == format_char() && *++str && *str != format_char())
+		{
+			switch (*str++)
+			{
+				case 'l': case 'L': tsize = 24; break;
+				case 'm': case 'M': tsize = 18; break;
+				case 's': tsize = 11; break;
+				case 'b': font = (Fl_Font)(font|FL_BOLD); break;
+				case 'i': font = (Fl_Font)(font|FL_ITALIC); break;
+				case 'f': case 't': font = FL_COURIER; break;
+				case 'c': talign = FL_ALIGN_CENTER; break;
+				case 'r': talign = FL_ALIGN_RIGHT; break;
+				case 'B': 
+					if (!item_selected(p))
+					{
+						fl_color((Fl_Color)strtol(str, &str, 10));
+						fl_rectf(x, y, w1, h);
+					}
+					else
+						strtol(str, &str, 10);
+					break;
+				case 'C': lcol = (Fl_Color)strtol(str, &str, 10); break;
+				case 'F': font = (Fl_Font)strtol(str, &str, 10); break;
+				case 'N': lcol = FL_INACTIVE_COLOR; break;
+				case 'S': tsize = strtol(str, &str, 10); break;
+				case '-':
+					fl_color(FL_DARK3);
+					fl_line(x + 3, y + h/2, x + w1 - 3, y + h/2);
+					fl_color(FL_LIGHT3);
+					fl_line(x + 3, y + h/2 + 1, x + w1 - 3, y + h/2 + 1);
+					break;
+				case 'u':
+				case '_':
+					fl_color(lcol);
+					fl_line(x + 3, y + h - 1, x + w1 - 3, y + h - 1);
+					break;
+				case '.': goto BREAK;
+				case '@': str--; goto BREAK;
+			}
+		}
+
+	BREAK:
+		fl_font(font, tsize);
+		if (item_selected(p))
+			lcol = fl_contrast(lcol, selection_color());
+		if (!active_r()) lcol = fl_inactive(lcol);
+		fl_color(lcol);
+
+		if (*str=='%' && '0'<=str[1] && str[1]<='9')
+		{
+			char *after;
+			int percent = strtol(str+1, &after, 10);
+			int steps = 0;
+			unsigned int bar = 0;
+			if (after && *after=='/')
+				steps = strtol(after+1, &after, 10);
+			if (steps < 0 ) steps = 100;
+			if (after && *after=='/')
+				bar = strtol(after+1, &after, 10);
+			if (bar >= num_bar_images ) bar = num_bar_images - 1;
+			if (bar < 0 ) bar = 0;
+			int n = (percent + (50/steps))* steps / 100; // convert to num of steps, round instead of just floor
+			if (n < 0) n = 0;
+			if (n > steps) n = steps;
+			Fl_Image *bar_off = bar_images[bar*2+1];
+			Fl_Image *bar_on = bar_images[bar*2];
+			int active = bar_on->w()*n/steps;
+
+			if (bar_off)
+				bar_off->draw(x + active + 3, y, min(bar_off->w() - active, w1 - active - 6), h, active, 0);
+			if (bar_on)
+				bar_on->draw(x + 3, y, min(active, w1 - 6), h, 0, 0);
+
+			char tmp[32];
+			snprintf(tmp, sizeof(tmp), "%u%%", percent);
+			//fl_draw(tmp, x + 3, y, min(bar_off->w(), w1) - 6, h, Fl_Align(FL_ALIGN_CENTER|FL_ALIGN_CLIP), 0, 0);
+			//fl_draw(tmp, x + bar_on->w() + 3, y, w1 - 6, h, Fl_Align(FL_ALIGN_LEFT|FL_ALIGN_CLIP), 0, 0);
+		}
+		else
+		{
+			fl_draw(str, x + 3, y, w1 - 6, h, e ? Fl_Align(talign|FL_ALIGN_CLIP) : talign, 0, 0);
+		}
+
+		if (!e) break; // no more fields...
+		*e = column_char(); // put the seperator back
+		x += w1;
+		w -= w1;
+		str = e+1;
+	}
+
+	free (text);
+}
+
+int PackageBrowser::handle(int e)
+{
+//	printf("PackageBrowser::handle(int e = 0x%)\n", e);
+//	fflush(stdout);
+
+	int ret = VersatileBrowser::handle(e);
+
+	switch(e)
+	{
+		case FL_PUSH:
+			break;
+		case FL_RELEASE:
+			break;
+		case FL_ENTER:
+			break;
+		case FL_LEAVE:
+			break;
+		case FL_DRAG:
+			break;
+		case FL_FOCUS:
+			break;
+		case FL_UNFOCUS:
+			break;
+		case FL_KEYDOWN:
+			break;
+		case FL_KEYUP:
+			break;
+		case FL_CLOSE:
+			break;
+		case FL_MOVE:
+			break;
+		case FL_SHORTCUT:
+			break;
+		case FL_DEACTIVATE:
+			break;
+		case FL_ACTIVATE:
+			break;
+		case FL_HIDE:
+			break;
+		case FL_SHOW:
+			break;
+		case FL_PASTE:
+			break;
+		case  FL_SELECTIONCLEAR:
+			break;
+		case  FL_MOUSEWHEEL:
+			break;
+		case  FL_NO_EVENT:
+			break;
+	}
+	return ret;
+}
diff --git a/fltk/pkgbrowser.h b/fltk/pkgbrowser.h
new file mode 100644
index 0000000..ee2cf7b
--- /dev/null
+++ b/fltk/pkgbrowser.h
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2007, 2008  Miriam Ruiz <little_miry at yahoo.es>
+ *
+ * VersatileBrowser uses ColResizeBrowser, written by Greg Ercolano
+ * ColResizeBrowser (C) Greg Ercolano <erco at seriss.com>
+ * URL: http://seriss.com/people/erco/fltk/
+ * GNU GPL License (version 2 or, at your option, any later version)
+ *
+ * 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
+ */
+
+#ifndef _GOFIND_FLTK_PKGBROWSER_H
+#define _GOFIND_FLTK_PKGBROWSER_H
+
+#include <stdlib.h>
+
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+#include <FL/Fl_Browser.H>
+#include <FL/Fl_Help_View.H>
+#include <FL/fl_draw.H>
+
+//
+// Demonstrate how to derive a class extending Fl_Browser with interactively resizable columns
+// erco 1.10 12/09/2005
+//
+class VersatileBrowser : public Fl_Browser
+{
+    Fl_Color  _colsepcolor;	// color of column separator lines 
+    int       _showcolsep;	// flag to enable drawing column separators
+    Fl_Cursor _last_cursor;	// saved cursor state info
+    int       _dragging;	// 1=user dragging a column
+    int       _dragcol;		// col# user is currently dragging
+    int      *_widths;		// pointer to user's width[] array
+    int       _nowidths[1];	// default width array (non-const)
+    // CHANGE CURSOR
+    //     Does nothing if cursor already set to value specified.
+    //
+    void change_cursor(Fl_Cursor newcursor) {
+        if ( newcursor != _last_cursor ) {
+            fl_cursor(newcursor, FL_BLACK, FL_WHITE);
+            _last_cursor = newcursor;
+        }
+    }
+    // RETURN THE COLUMN MOUSE IS 'NEAR'
+    //     Returns -1 if none.
+    //
+    int which_col_near_mouse() {
+        int X,Y,W,H;
+        Fl_Browser::bbox(X,Y,W,H); // area inside browser's box()
+        // EVENT NOT INSIDE BROWSER AREA? (eg. on a scrollbar)
+        if ( ! Fl::event_inside(X,Y,W,H) ) {
+            return(-1);
+        }
+        int mousex = Fl::event_x() + hposition();
+        int colx = this->x();
+        for ( int t=0; _widths[t]; t++ ) {
+            colx += _widths[t];
+            int diff = mousex - colx;
+            // MOUSE 'NEAR' A COLUMN?
+            //     Return column #
+            //
+            if ( diff >= -4 && diff <= 4 ) {
+                return(t);
+            }
+        }
+        return(-1);
+    }
+
+protected:
+    // MANAGE EVENTS TO HANDLE COLUMN RESIZING
+    int handle(int e) {
+    // Not showing column separators? Use default Fl_Browser::handle() logic
+    if ( ! showcolsep() ) return(Fl_Browser::handle(e));
+        // Handle column resizing
+        int ret = 0;
+        switch ( e ) {
+            case FL_ENTER: {
+                ret = 1;
+                break;
+            }
+            case FL_MOVE: {
+                if ( which_col_near_mouse() >= 0 ) {
+                    change_cursor(FL_CURSOR_WE);
+                } else {
+                    change_cursor(FL_CURSOR_DEFAULT);
+                }
+                ret = 1;
+                break;
+            }
+            case FL_PUSH: {
+                int whichcol = which_col_near_mouse();
+                if ( whichcol >= 0 ) {
+                    // CLICKED ON RESIZER? START DRAGGING
+                    ret = 1;
+                    _dragging = 1;
+                    _dragcol = whichcol;
+                    change_cursor(FL_CURSOR_DEFAULT);
+                }
+                break;
+            }
+            case FL_DRAG: {
+                if ( _dragging ) {
+                    ret = 1;
+                    // Sum up column widths to determine position
+                    int mousex = Fl::event_x() + hposition();
+                    int newwidth = mousex - x();
+                    for ( int t=0; _widths[t] && t<_dragcol; t++ ) {
+                        newwidth -= _widths[t];
+                    }
+                    if ( newwidth > 0 ) {
+                        // Apply new width, redraw interface
+                        _widths[_dragcol] = newwidth;
+                        if ( _widths[_dragcol] < 2 ) {
+                            _widths[_dragcol] = 2;
+                        }
+                        redraw();
+                    }
+                }
+                break;
+            }
+            case FL_LEAVE:
+            case FL_RELEASE: {
+                _dragging = 0; // disable drag mode
+                change_cursor(FL_CURSOR_DEFAULT); // ensure normal cursor
+                ret = 1;
+                break;
+            }
+        }
+        if ( _dragging ) return(1); // dragging? don't pass event to Fl_Browser
+        return(Fl_Browser::handle(e) ? 1 : ret);
+    }
+    void draw() {
+        // DRAW BROWSER
+        Fl_Browser::draw();
+        if ( _showcolsep ) {
+            // DRAW COLUMN SEPARATORS
+            int colx = this->x() - hposition();
+            int X,Y,W,H;
+            Fl_Browser::bbox(X,Y,W,H);
+            fl_color(_colsepcolor);
+            for ( int t=0; _widths[t]; t++ ) {
+                colx += _widths[t];
+                if ( colx > X && colx < (X+W) ) {
+                    fl_line(colx, Y, colx, Y+H-1);
+                }
+            }
+        }
+    }
+public:
+    // CTOR
+    VersatileBrowser(int X,int Y,int W,int H,const char*L=NULL) : Fl_Browser(X,Y,W,H,L) {
+        _colsepcolor = Fl_Color(FL_GRAY);
+        _last_cursor = FL_CURSOR_DEFAULT;
+        _showcolsep  = 0;
+        _dragging    = 0;
+        _nowidths[0] = 0;
+        _widths      = _nowidths;
+    }
+    // GET/SET COLUMN SEPARATOR LINE COLOR
+    Fl_Color colsepcolor() const {
+        return(_colsepcolor);
+    }
+    void colsepcolor(Fl_Color val) {
+        _colsepcolor = val;
+    }
+    // GET/SET DISPLAY OF COLUMN SEPARATOR LINES
+    //     1: show lines, 0: don't show lines
+    //
+    int showcolsep() const {
+        return(_showcolsep);
+    }
+    void showcolsep(int val) {
+        _showcolsep = val;
+    }
+    // GET/SET COLUMN WIDTHS ARRAY
+    //    Just like fltk method, but array is non-const.
+    //
+    int *column_widths() const {
+        return(_widths);
+    }
+    void column_widths(int *val) {
+        _widths = val;
+        Fl_Browser::column_widths(val);
+    }
+};
+
+class PackageBrowser : public VersatileBrowser
+{
+public:
+	PackageBrowser(int x, int y, int w, int h, const char *l = NULL);
+	virtual ~PackageBrowser();
+
+protected:
+	virtual void item_select(void *p, int s=1);
+	virtual int item_width(void *p) const;
+	virtual void item_draw(void *p, int x, int y, int w, int h)  const;
+	virtual int handle(int e);
+
+private:
+	const unsigned int num_bar_images;
+	Fl_Image *bar_images[2*2];
+};
+
+class PackageView : public Fl_Help_View
+{
+public:
+	PackageView(int xx, int yy, int ww, int hh, const char *l = 0);
+
+private:
+	static const char *link_cb(Fl_Widget *w, const char *uri);
+};
+
+#endif // _GOFIND_FLTK_PKGBROWSER_H
diff --git a/fltk/ui.cpp b/fltk/ui.cpp
new file mode 100644
index 0000000..4544d0b
--- /dev/null
+++ b/fltk/ui.cpp
@@ -0,0 +1,203 @@
+// generated by Fast Light User Interface Designer (fluid) version 1.0109
+
+#include "../common.h"
+#include "ui.h"
+
+Fl_Menu_Item GamesUI::menu_TypeSelection[] = {
+ {_("Any type"), 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
+ {0,0,0,0,0,0,0,0,0}
+};
+
+Fl_Menu_Item GamesUI::menu_InterfaceSelection[] = {
+ {_("Any interface"), 0,  0, 0, 0, FL_NORMAL_LABEL, 0, 14, 0},
+ {0,0,0,0,0,0,0,0,0}
+};
+
+void GamesUI::cb__i(Fl_Button*, void*) {
+  AboutWindow->show();
+}
+void GamesUI::cb_(Fl_Button* o, void* v) {
+  ((GamesUI*)(o->parent()->parent()->user_data()))->cb__i(o,v);
+}
+
+GamesUI::GamesUI() {
+}
+
+GamesUI::~GamesUI() {
+  if (ScreenshotWidget->image() == NULL) {
+    Fl_Image *i=ScreenshotWidget->image();
+    ScreenshotWidget->image(NULL);
+    delete i;
+  }
+}
+
+void GamesUI::Resize(int w, int h) {
+  static const int border = 6;
+static const int vgap = 4;
+static const int hgap = 6;
+
+if (w < 710) w = 710;
+if (h < 500) h = 500;
+
+int x_ref = w - 320 - border;
+int h_info_tags = (h - 240 - border * 2 - vgap * 2);
+int h_info = h_info_tags * 2 / 3;
+int h_tags = h_info_tags - h_info;
+
+if (InputGroup)
+	InputGroup->resize(border, border, x_ref - border - hgap, 120);
+if (ResultsBrowser)
+	ResultsBrowser->resize(border, 120 + border + vgap, x_ref - border - hgap, h - 120 - border * 2 - vgap);
+
+if (ScreenshotWidget)
+	ScreenshotWidget->resize(x_ref, border, 320, 240);
+if (InfoView)
+	InfoView->resize(x_ref, border + 240 + vgap, 320, h_info);
+if (DebTagsBrowser)
+	DebTagsBrowser->resize(x_ref, border + 240 + h_info + vgap * 2, 320, h_tags);
+}
+
+void GamesUI::Screenshot(Fl_Image *img) {
+  Fl_Image *i=ScreenshotWidget->image();
+  ScreenshotWidget->image(img);
+  if (i != NULL) {
+    delete i;
+  }
+  ScreenshotWidget->redraw();
+}
+
+MainWindow* GamesUI::CreateMainWindow() {
+  { Window = new MainWindow(710, 525);
+    Window->box(FL_FLAT_BOX);
+    Window->color(FL_BACKGROUND_COLOR);
+    Window->selection_color(FL_BACKGROUND_COLOR);
+    Window->labeltype(FL_NO_LABEL);
+    Window->labelfont(0);
+    Window->labelsize(14);
+    Window->labelcolor(FL_FOREGROUND_COLOR);
+    Window->user_data((void*)(this));
+    Window->align(FL_ALIGN_TOP);
+    Window->when(FL_WHEN_RELEASE);
+    { InputGroup = new Fl_Group(5, 16, 375, 118);
+      InputGroup->box(FL_UP_FRAME);
+      { SearchInput = new Fl_Input(65, 95, 300, 25, _("Search"));
+        SearchInput->labelsize(12);
+      } // Fl_Input* SearchInput
+      { TypeSelection = new Fl_Choice(70, 60, 120, 25, _("Type"));
+        TypeSelection->down_box(FL_BORDER_BOX);
+        TypeSelection->labelsize(12);
+        TypeSelection->when(FL_WHEN_CHANGED);
+        TypeSelection->menu(menu_TypeSelection);
+      } // Fl_Choice* TypeSelection
+      { InterfaceSelection = new Fl_Choice(260, 60, 115, 25, _("Interface"));
+        InterfaceSelection->down_box(FL_BORDER_BOX);
+        InterfaceSelection->labelsize(12);
+        InterfaceSelection->menu(menu_InterfaceSelection);
+      } // Fl_Choice* InterfaceSelection
+      { Fl_Group* o = new Fl_Group(13, 25, 312, 30);
+        { AlreadyInstalled = new Fl_Round_Button(13, 28, 110, 20, _("Already installed"));
+          AlreadyInstalled->down_box(FL_ROUND_DOWN_BOX);
+          AlreadyInstalled->labelsize(12);
+        } // Fl_Round_Button* AlreadyInstalled
+        { ToBeInstalled = new Fl_Round_Button(138, 28, 110, 20, _("To be installed"));
+          ToBeInstalled->down_box(FL_ROUND_DOWN_BOX);
+          ToBeInstalled->labelsize(12);
+        } // Fl_Round_Button* ToBeInstalled
+        { InstalledOrNot = new Fl_Round_Button(251, 28, 65, 20, _("Both"));
+          InstalledOrNot->down_box(FL_ROUND_DOWN_BOX);
+          InstalledOrNot->value(1);
+          InstalledOrNot->labelsize(12);
+        } // Fl_Round_Button* InstalledOrNot
+        o->end();
+      } // Fl_Group* o
+      { Fl_Button* o = new Fl_Button(340, 20, 35, 35);
+        o->box(FL_NO_BOX);
+        o->callback((Fl_Callback*)cb_);
+      } // Fl_Button* o
+      InputGroup->end();
+    } // Fl_Group* InputGroup
+    { ScreenshotWidget = new Fl_Box(385, 15, 320, 240);
+      ScreenshotWidget->box(FL_FLAT_BOX);
+      ScreenshotWidget->color(FL_GRAY0);
+      ScreenshotWidget->selection_color(FL_GRAY0);
+    } // Fl_Box* ScreenshotWidget
+    { ResultsBrowser = new PackageBrowser(5, 140, 375, 375);
+      ResultsBrowser->type(2);
+      ResultsBrowser->box(FL_NO_BOX);
+      ResultsBrowser->color(FL_BACKGROUND2_COLOR);
+      ResultsBrowser->selection_color(FL_SELECTION_COLOR);
+      ResultsBrowser->labeltype(FL_NORMAL_LABEL);
+      ResultsBrowser->labelfont(0);
+      ResultsBrowser->labelsize(14);
+      ResultsBrowser->labelcolor(FL_FOREGROUND_COLOR);
+      ResultsBrowser->textsize(12);
+      ResultsBrowser->align(FL_ALIGN_CENTER);
+      ResultsBrowser->when(FL_WHEN_RELEASE_ALWAYS);
+    } // PackageBrowser* ResultsBrowser
+    { DebTagsBrowser = new VersatileBrowser(385, 435, 320, 80);
+      DebTagsBrowser->box(FL_NO_BOX);
+      DebTagsBrowser->color(FL_BACKGROUND2_COLOR);
+      DebTagsBrowser->selection_color(FL_SELECTION_COLOR);
+      DebTagsBrowser->labeltype(FL_NORMAL_LABEL);
+      DebTagsBrowser->labelfont(0);
+      DebTagsBrowser->labelsize(14);
+      DebTagsBrowser->labelcolor(FL_FOREGROUND_COLOR);
+      DebTagsBrowser->textsize(11);
+      DebTagsBrowser->align(FL_ALIGN_CENTER);
+      DebTagsBrowser->when(FL_WHEN_RELEASE_ALWAYS);
+    } // VersatileBrowser* DebTagsBrowser
+    { InfoView = new HTMLView(385, 260, 320, 170);
+      InfoView->box(FL_NO_BOX);
+      InfoView->color(FL_BACKGROUND2_COLOR);
+      InfoView->selection_color(FL_SELECTION_COLOR);
+      InfoView->labeltype(FL_NORMAL_LABEL);
+      InfoView->labelfont(0);
+      InfoView->labelsize(14);
+      InfoView->labelcolor(FL_FOREGROUND_COLOR);
+      InfoView->align(FL_ALIGN_TOP);
+      InfoView->when(FL_WHEN_RELEASE);
+    } // HTMLView* InfoView
+    Window->end();
+    Window->resizable(Window);
+  } // MainWindow* Window
+  Window->size_range(710, 500);
+  return Window;
+}
+
+Fl_Double_Window* GamesUI::CreateAboutWindow() {
+  { AboutWindow = new Fl_Double_Window(520, 430);
+    AboutWindow->user_data((void*)(this));
+    { AboutView = new HTMLView(5, 75, 510, 350);
+      AboutView->box(FL_NO_BOX);
+      AboutView->color(FL_BACKGROUND2_COLOR);
+      AboutView->selection_color(FL_SELECTION_COLOR);
+      AboutView->labeltype(FL_NORMAL_LABEL);
+      AboutView->labelfont(0);
+      AboutView->labelsize(14);
+      AboutView->labelcolor(FL_FOREGROUND_COLOR);
+      AboutView->align(FL_ALIGN_TOP);
+      AboutView->when(FL_WHEN_RELEASE);
+    } // HTMLView* AboutView
+    { AboutStar = new Fl_Button(400, 5, 90, 90);
+      AboutStar->box(FL_NO_BOX);
+      AboutStar->deactivate();
+    } // Fl_Button* AboutStar
+    AboutWindow->end();
+  } // Fl_Double_Window* AboutWindow
+  AboutWindow->clear_visible_focus();
+  AboutView->SetDrawCallback(AboutViewUpdated);
+  return AboutWindow;
+}
+
+MainWindow * GamesUI::CreateWindows() {
+  CreateMainWindow();
+CreateAboutWindow();
+return Window;
+}
+
+void GamesUI::AboutViewUpdated(HTMLView *item) {
+  Fl_Group *highest_parent=item->parent();
+while (highest_parent->parent()) highest_parent = highest_parent->parent();
+GamesUI *ui = highest_parent ? (GamesUI*)(highest_parent->user_data()) : NULL;
+ui->AboutStar->redraw();
+}
diff --git a/fltk/ui.fld b/fltk/ui.fld
new file mode 100644
index 0000000..a1c44ee
--- /dev/null
+++ b/fltk/ui.fld
@@ -0,0 +1,170 @@
+# data file for the Fltk User Interface Designer (fluid)
+version 1.0109 
+i18n_type 1 
+i18n_include "../common.h" 
+i18n_function _ 
+header_name {.h} 
+code_name {.cpp}
+decl {\#include "../common.h"} {public
+} 
+
+decl {\#include "aux.h"} {public
+} 
+
+decl {\#include "pkgbrowser.h"} {public
+} 
+
+decl {\#include "windows.h"} {public
+} 
+
+class GamesUI {open
+} {
+  Function {GamesUI()} {open
+  } {
+    code {} {}
+  }
+  Function {~GamesUI()} {open
+  } {
+    code {if (ScreenshotWidget->image() == NULL) {
+    Fl_Image *i=ScreenshotWidget->image();
+    ScreenshotWidget->image(NULL);
+    delete i;
+  }} {}
+  }
+  Function {Resize(int w, int h)} {open return_type void
+  } {
+    code {static const int border = 6;
+static const int vgap = 4;
+static const int hgap = 6;
+
+if (w < 710) w = 710;
+if (h < 500) h = 500;
+
+int x_ref = w - 320 - border;
+int h_info_tags = (h - 240 - border * 2 - vgap * 2);
+int h_info = h_info_tags * 2 / 3;
+int h_tags = h_info_tags - h_info;
+
+if (InputGroup)
+	InputGroup->resize(border, border, x_ref - border - hgap, 120);
+if (ResultsBrowser)
+	ResultsBrowser->resize(border, 120 + border + vgap, x_ref - border - hgap, h - 120 - border * 2 - vgap);
+
+if (ScreenshotWidget)
+	ScreenshotWidget->resize(x_ref, border, 320, 240);
+if (InfoView)
+	InfoView->resize(x_ref, border + 240 + vgap, 320, h_info);
+if (DebTagsBrowser)
+	DebTagsBrowser->resize(x_ref, border + 240 + h_info + vgap * 2, 320, h_tags);} {}
+  }
+  Function {Screenshot(Fl_Image *img)} {open return_type void
+  } {
+    code {Fl_Image *i=ScreenshotWidget->image();
+  ScreenshotWidget->image(img);
+  if (i != NULL) {
+    delete i;
+  }
+  ScreenshotWidget->redraw();} {}
+  }
+  Function {CreateMainWindow()} {open
+  } {
+    Fl_Window Window {open
+      xywh {337 80 710 525} type Single resizable
+      class MainWindow visible
+    } {
+      Fl_Group InputGroup {open
+        xywh {5 16 375 118} box UP_FRAME
+      } {
+        Fl_Input SearchInput {
+          label Search
+          xywh {65 95 300 25} labelsize 12
+        }
+        Fl_Choice TypeSelection {
+          label Type open
+          xywh {70 60 120 25} down_box BORDER_BOX labelsize 12 when 1
+        } {
+          MenuItem {} {
+            label {Any type}
+            xywh {25 25 100 20}
+          }
+        }
+        Fl_Choice InterfaceSelection {
+          label Interface open
+          xywh {260 60 115 25} down_box BORDER_BOX labelsize 12
+        } {
+          MenuItem {} {
+            label {Any interface}
+            xywh {25 25 100 20}
+          }
+        }
+        Fl_Group {} {open
+          xywh {13 25 312 30}
+        } {
+          Fl_Round_Button AlreadyInstalled {
+            label {Already installed}
+            xywh {13 28 110 20} down_box ROUND_DOWN_BOX labelsize 12
+          }
+          Fl_Round_Button ToBeInstalled {
+            label {To be installed}
+            xywh {138 28 110 20} down_box ROUND_DOWN_BOX labelsize 12
+          }
+          Fl_Round_Button InstalledOrNot {
+            label Both
+            xywh {251 28 65 20} down_box ROUND_DOWN_BOX value 1 labelsize 12
+          }
+        }
+        Fl_Button {} {
+          callback {AboutWindow->show();}
+          image {data/icons/Icon32.png} xywh {340 20 35 35} box NO_BOX
+        }
+      }
+      Fl_Box ScreenshotWidget {
+        xywh {385 15 320 240} box FLAT_BOX color 32 selection_color 32
+      }
+      Fl_Browser ResultsBrowser {
+        xywh {5 140 375 375} type Hold align 0 textsize 12
+        class PackageBrowser
+      }
+      Fl_Browser DebTagsBrowser {
+        xywh {385 435 320 80} align 0 textsize 11
+        class VersatileBrowser
+      }
+      Fl_Help_View InfoView {
+        xywh {385 260 320 170}
+        class HTMLView
+      }
+    }
+    code {Window->size_range(710, 500);} {}
+  }
+  decl {void *user_data;} {selected public
+  }
+  Function {CreateAboutWindow()} {open
+  } {
+    Fl_Window AboutWindow {open
+      xywh {706 245 520 430} type Double visible
+    } {
+      Fl_Help_View AboutView {
+        xywh {5 75 510 350}
+        class HTMLView
+      }
+      Fl_Button AboutStar {
+        private image {data/icons/Rating.png} xywh {400 5 90 90} box NO_BOX deactivate
+      }
+    }
+    code {AboutWindow->clear_visible_focus();} {}
+    code {AboutView->SetDrawCallback(AboutViewUpdated);} {}
+  }
+  Function {CreateWindows()} {open return_type {MainWindow *}
+  } {
+    code {CreateMainWindow();
+CreateAboutWindow();
+return Window;} {}
+  }
+  Function {AboutViewUpdated(HTMLView *item)} {open return_type {static void}
+  } {
+    code {Fl_Group *highest_parent=item->parent();
+while (highest_parent->parent()) highest_parent = highest_parent->parent();
+GamesUI *ui = highest_parent ? (GamesUI*)(highest_parent->user_data()) : NULL;
+ui->AboutStar->redraw();} {}
+  }
+} 
diff --git a/fltk/ui.h b/fltk/ui.h
new file mode 100644
index 0000000..0981cea
--- /dev/null
+++ b/fltk/ui.h
@@ -0,0 +1,53 @@
+// generated by Fast Light User Interface Designer (fluid) version 1.0109
+
+#ifndef ui_h
+#define ui_h
+#include <FL/Fl.H>
+#include "../common.h"
+#include "aux.h"
+#include "pkgbrowser.h"
+#include "windows.h"
+#include <FL/Fl_Group.H>
+#include <FL/Fl_Input.H>
+#include <FL/Fl_Choice.H>
+#include <FL/Fl_Round_Button.H>
+#include <FL/Fl_Button.H>
+#include <FL/Fl_Box.H>
+#include <FL/Fl_Double_Window.H>
+
+class GamesUI {
+public:
+  GamesUI();
+  ~GamesUI();
+  void Resize(int w, int h);
+  void Screenshot(Fl_Image *img);
+  MainWindow* CreateMainWindow();
+  MainWindow *Window;
+  Fl_Group *InputGroup;
+  Fl_Input *SearchInput;
+  Fl_Choice *TypeSelection;
+  static Fl_Menu_Item menu_TypeSelection[];
+  Fl_Choice *InterfaceSelection;
+  static Fl_Menu_Item menu_InterfaceSelection[];
+  Fl_Round_Button *AlreadyInstalled;
+  Fl_Round_Button *ToBeInstalled;
+  Fl_Round_Button *InstalledOrNot;
+private:
+  void cb__i(Fl_Button*, void*);
+  static void cb_(Fl_Button*, void*);
+public:
+  Fl_Box *ScreenshotWidget;
+  PackageBrowser *ResultsBrowser;
+  VersatileBrowser *DebTagsBrowser;
+  HTMLView *InfoView;
+  void *user_data; 
+  Fl_Double_Window* CreateAboutWindow();
+  Fl_Double_Window *AboutWindow;
+  HTMLView *AboutView;
+private:
+  Fl_Button *AboutStar;
+public:
+  MainWindow * CreateWindows();
+  static void AboutViewUpdated(HTMLView *item);
+};
+#endif
diff --git a/cfgmanager.cpp b/fltk/windows.cpp
similarity index 53%
copy from cfgmanager.cpp
copy to fltk/windows.cpp
index e88b595..ab61072 100644
--- a/cfgmanager.cpp
+++ b/fltk/windows.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008  Miriam Ruiz <little_miry at yahoo.es>
+ * Copyright (C) 2007  Miriam Ruiz <little_miry at yahoo.es>
  *
  * 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
@@ -16,19 +16,24 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include "common.h"
-#include "cfgmanager.h"
+#include "windows.h"
+#include "ui.h"
 
-ConfigManager::ConfigManager()
+#include <stdio.h>
+
+MainWindow::MainWindow(int w, int h, const char *label) : Fl_Double_Window(w, h, label)
 {
 }
 
-ConfigManager::~ConfigManager()
+MainWindow::MainWindow(int x, int y, int w, int h, const char *label) : Fl_Double_Window(x, y, w, h, label)
 {
 }
 
-#ifdef UNIT_TEST
-TEST_FUNCTION TestCuConfigManager(CuTest* tc)
+void MainWindow::resize(int x, int y, int w, int h)
 {
+	Fl_Double_Window::resize(x, y, w, h);
+	Fl_Group *highest_parent=this;
+	while (highest_parent->parent()) highest_parent = highest_parent->parent();
+	GamesUI *ui = highest_parent ? (GamesUI*)(highest_parent->user_data()) : NULL;
+	ui->Resize(Fl_Double_Window::w(), Fl_Double_Window::h());
 }
-#endif
diff --git a/cfgmanager.h b/fltk/windows.h
similarity index 64%
copy from cfgmanager.h
copy to fltk/windows.h
index 8c6d57a..a8dd413 100644
--- a/cfgmanager.h
+++ b/fltk/windows.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008  Miriam Ruiz <little_miry at yahoo.es>
+ * Copyright (C) 2007  Miriam Ruiz <little_miry at yahoo.es>
  *
  * 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
@@ -16,23 +16,21 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef _GOFIND_CONFIGMANAGER_H
-#define _GOFIND_CONFIGMANAGER_H
+#ifndef _GOFIND_FLTK_WINDOWS_H
+#define _GOFIND_FLTK_WINDOWS_H
 
-class ConfigManager
+#include <FL/Fl.H>
+#include <FL/Fl_Double_Window.H>
+
+class MainWindow : public Fl_Double_Window
 {
 public:
-    /**
-        Initializes the configuration manager.
-    */
-    ConfigManager();
+	MainWindow(int w, int h, const char *label = 0);
+	MainWindow(int x, int y, int w, int h, const char *label = 0);
 
-    /**
-        Destroys the configuration manager and frees the associated resources.
-    */
-    ~ConfigManager();
+	virtual void resize(int x, int y, int w, int h);
 
 private:
 };
 
-#endif // _GOFIND_CONFIGMANAGER_H
+#endif // _GOFIND_FLTK_WINDOWS_H
diff --git a/gofind.cpp b/gofind.cpp
index 809404c..48efc97 100644
--- a/gofind.cpp
+++ b/gofind.cpp
@@ -328,7 +328,9 @@ int main(int argc, const char* argv[])
 	bindtextdomain ("gofind", NULL);
 #endif
 
-	DLLFactory<GUIPlugInFactory> gui_factory( "./gui_cli.so" );
+//	DLLFactory<GUIPlugInFactory> gui_factory( "./gui_cli.so" );
+	DLLFactory<GUIPlugInFactory> gui_factory( "./gui_fltk.so" );
+
 	if( ! gui_factory.factory )
 	{
 		std::cout << _("Could not load GUI plugin") << std::endl;
diff --git a/gui_fltk.cpp b/gui_fltk.cpp
new file mode 100644
index 0000000..e97f486
--- /dev/null
+++ b/gui_fltk.cpp
@@ -0,0 +1,249 @@
+/*
+ * debtags - Implement package tags support for Debian
+ *
+ * Copyright (C) 2007  Enrico Zini <enrico at debian.org>
+ * Copyright (C) 2007, 2008  Miriam Ruiz <little_miry at yahoo.es>
+ *
+ * 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
+ */
+
+#include "common.h"
+#include "guiplugin.h"
+#include "fltk/ui.h"
+
+#include <FL/Fl.H>
+#include <FL/Fl_PNG_Image.H>
+#include <FL/fl_ask.H>
+
+#ifdef USE_GETTEXT
+#include <libintl.h>
+#include <locale.h>
+#else
+// Work-around until goplay is actually gettextised
+#define gettext(a) (a)
+#endif
+
+#include <stdarg.h>
+#include <string.h>
+
+class GUIPlugInFLTK : public GUIPlugIn
+{
+ public:
+	GUIPlugInFLTK(GUIPlugInFactory *f) : GUIPlugIn(f)
+	{
+		std::cout << "GUIPlugInFLTK() Created" << std::endl;
+	}
+
+	virtual ~GUIPlugInFLTK()
+	{
+		std::cout << "GUIPlugInFLTK() destroyed" << std::endl;
+	}
+
+	virtual void Comment(const char *szFormat, ...);
+	virtual bool Go(GUIPlugInData &data);
+};
+
+void GUIPlugInFLTK::Comment(const char *szFormat, ...)
+{
+	char str[4096];
+	va_list arglist;
+
+	*str = '\0';
+
+	va_start(arglist, szFormat);
+	vsprintf(str + strlen(str), szFormat, arglist);
+	va_end(arglist);
+
+	std::cout << "# " << str << std::endl;
+}
+
+
+
+static void UpdateUILists(GamesUI& ui)
+{
+	// Defining this here, non-const, because fltk's interface want non-const
+	// strings and I did not have time to check whether it would attempt to
+	// modify the parameter or not.  Likely not, and thus a
+	// const_cast<char*>(VoidString) would probably have been better.
+	// --Enrico
+	char VoidString[1] = "";
+//	const char* oldType = ReadFlChoice(*ui.TypeSelection);
+//	const char* oldIface = ReadFlChoice(*ui.InterfaceSelection);
+	ui.TypeSelection->clear();
+	ui.TypeSelection->add(_("Any type"), 0, NULL, VoidString, FL_NORMAL_LABEL);
+	ui.InterfaceSelection->clear();
+	ui.InterfaceSelection->add(_("Any interface"), 0, NULL, VoidString, FL_NORMAL_LABEL);
+
+	bool PopconAvailable = true;
+	static int widths_with_popcon[] = { 100, 300, 0 }; // widths for each column
+	static int widths_without_popcon[] = { 100, 0 };
+	ui.ResultsBrowser->clear();
+	if (PopconAvailable)
+	{
+		ui.ResultsBrowser->column_widths(widths_with_popcon);
+		// tab delimited columns with colors
+		ui.ResultsBrowser->add(_("@B12 at C7@b at .PACKAGE\t at B12@C7 at b@.DESCRIPTION\t at B12@C7 at b@.POPCON"));
+	}
+	else
+	{
+		ui.ResultsBrowser->column_widths(widths_without_popcon);
+		// tab delimited columns with colors
+		ui.ResultsBrowser->add(_("@B12 at C7@b at .PACKAGE\t at B12@C7 at b@.DESCRIPTION"));
+	}
+}
+
+static void CallBackTypeSelection(Fl_Choice* choice, void *data)
+{
+	//printf("CallBackTypeSelection\n");
+	//fflush(stdout);
+	GamesUI& ui = *static_cast<GamesUI*>(data);
+	UpdateUILists(ui);
+}
+
+static void CallBackInterfaceSelection(Fl_Choice* choice, void *data)
+{
+	//printf("CallBackInterfaceSelection\n");
+	//fflush(stdout);
+	GamesUI& ui = *static_cast<GamesUI*>(data);
+	UpdateUILists(ui);
+}
+
+static void CallBackSearchInput(Fl_Input* input, void *data)
+{
+	//printf("CallBackSearchInput\n"); fflush(stdout);
+	GamesUI& ui = *static_cast<GamesUI*>(data);
+	UpdateUILists(ui);
+}
+
+static void CallBackAlreadyInstalled(Fl_Round_Button*, void *data)
+{
+	//printf("CallBackInstalled\n"); fflush(stdout);
+	GamesUI& ui = *static_cast<GamesUI*>(data);
+	ui.AlreadyInstalled->value(1); ui.AlreadyInstalled->redraw();
+	ui.ToBeInstalled->value(0); ui.ToBeInstalled->redraw();
+	ui.InstalledOrNot->value(0); ui.InstalledOrNot->redraw();
+//	ui.engine->setInstalledFilter(Engine::INSTALLED);
+	UpdateUILists(ui);
+}
+
+static void CallBackToBeInstalled(Fl_Round_Button*, void *data)
+{
+	//printf("CallBackToBeInstalled\n"); fflush(stdout);
+	GamesUI& ui = *static_cast<GamesUI*>(data);
+	ui.AlreadyInstalled->value(0); ui.AlreadyInstalled->redraw();
+	ui.ToBeInstalled->value(1); ui.ToBeInstalled->redraw();
+	ui.InstalledOrNot->value(0); ui.InstalledOrNot->redraw();
+//	ui.engine->setInstalledFilter(Engine::NOTINSTALLED);
+	UpdateUILists(ui);
+}
+
+static void CallBackInstalledOrNot(Fl_Round_Button*, void *data)
+{
+	//printf("CallBackToBeInstalled\n"); fflush(stdout);
+	GamesUI& ui = *static_cast<GamesUI*>(data);
+	ui.AlreadyInstalled->value(0); ui.AlreadyInstalled->redraw();
+	ui.ToBeInstalled->value(0); ui.ToBeInstalled->redraw();
+	ui.InstalledOrNot->value(1); ui.InstalledOrNot->redraw();
+//	ui.engine->setInstalledFilter(Engine::ANY);
+	UpdateUILists(ui);
+}
+
+bool GUIPlugInFLTK::Go(GUIPlugInData &data)
+{
+#ifdef USE_GETTEXT
+	setlocale (LC_MESSAGES, "");
+	setlocale (LC_CTYPE, "");
+	setlocale (LC_COLLATE, "");
+	textdomain ("gofind");
+	bindtextdomain ("gofind", NULL);
+#endif
+
+	GamesUI mainui;
+	mainui.user_data = NULL;
+	Fl_Double_Window *window = mainui.CreateWindows();
+	mainui.TypeSelection->callback((Fl_Callback*)CallBackTypeSelection, &mainui);
+	mainui.TypeSelection->when(FL_WHEN_CHANGED);
+	mainui.InterfaceSelection->callback((Fl_Callback*)CallBackInterfaceSelection, &mainui);
+	mainui.InterfaceSelection->when(FL_WHEN_CHANGED);
+	mainui.SearchInput->callback((Fl_Callback*)CallBackSearchInput, &mainui);
+	mainui.SearchInput->when(FL_WHEN_CHANGED);
+	mainui.AlreadyInstalled->callback((Fl_Callback*)CallBackAlreadyInstalled, &mainui);
+	mainui.AlreadyInstalled->when(FL_WHEN_CHANGED);
+	mainui.ToBeInstalled->callback((Fl_Callback*)CallBackToBeInstalled, &mainui);
+	mainui.ToBeInstalled->when(FL_WHEN_CHANGED);
+	mainui.InstalledOrNot->callback((Fl_Callback*)CallBackInstalledOrNot, &mainui);
+	mainui.InstalledOrNot->when(FL_WHEN_CHANGED);
+
+	mainui.AlreadyInstalled->value(0); mainui.AlreadyInstalled->redraw();
+	mainui.ToBeInstalled->value(0); mainui.ToBeInstalled->redraw();
+	mainui.InstalledOrNot->value(1); mainui.InstalledOrNot->redraw();
+//	mainui.engine->setInstalledFilter(Engine::ANY);
+
+	mainui.Screenshot(new Fl_PNG_Image(FILE_NO_SCREENSHOT));
+	mainui.AboutView->load(HTMLDIR "/about.en.html");
+
+	UpdateUILists(mainui);
+
+	int argc = 1;
+	const char *argv[32] = { "test", NULL };
+
+	window->show(argc, (char**)argv);
+	while (Fl::wait());
+	return 0;
+}
+
+class GUIPlugInFLTKFactory : public GUIPlugInFactory
+{
+ public:
+	GUIPlugInFLTKFactory()
+	{
+#ifdef GUIPLUGIN_VERSION
+		if (version != GUIPlugInFactory::version)
+			fprintf(stderr, "Wrong GUI Plugin Version: Program = 0x%04X, Plugin = 0x%04X\n", GUIPlugInFactory::version, version );
+#endif
+	}
+
+	~GUIPlugInFLTKFactory()
+	{
+	}
+
+	virtual GUIPlugIn * CreatePlugIn()
+	{
+#ifdef GUIPLUGIN_VERSION
+		if (version != GUIPlugInFactory::version)
+			return NULL;
+#endif
+		return new GUIPlugInFLTK(this);
+	}
+
+ protected:
+#ifdef GUIPLUGIN_VERSION
+	const static unsigned int version;
+#endif
+};
+
+#ifdef GUIPLUGIN_VERSION
+	const unsigned int GUIPlugInFLTKFactory::version = GUIPLUGIN_VERSION;
+#endif
+
+//
+// The "C" linkage factory0() function creates the PlugIn Factory
+// class for this library
+//
+
+extern "C" void * factory0( void )
+{
+	return new GUIPlugInFLTKFactory;
+}

-- 
Development fot GoFind!



More information about the Pkg-games-commits mailing list