The following commit has been merged in the master branch:
commit 8eb067988ba21988e57f90e0fa3fb1dccb314fdb
Author: Miriam Ruiz <[EMAIL PROTECTED]>
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:[EMAIL PROTECTED]">Miriam Ruiz</a><br />
+Copyright (C) 2007  <a href="mailto:[EMAIL PROTECTED]">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 <[EMAIL PROTECTED]>
+ *
+ * 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 <[EMAIL PROTECTED]>
+ * Copyright (C) 2007  Miriam Ruiz <[EMAIL PROTECTED]>
  *
  * 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 <[EMAIL PROTECTED]>
+ *
+ * VersatileBrowser uses ColResizeBrowser, written by Greg Ercolano
+ * ColResizeBrowser (C) Greg Ercolano <[EMAIL PROTECTED]>
+ * 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[] = "[EMAIL PROTECTED],.~/%&=:*#";
+
+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(_("@[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@[EMAIL PROTECTED]@[EMAIL PROTECTED]"));
+/*
+                       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, "@[EMAIL 
PROTECTED]@[EMAIL PROTECTED]@[EMAIL PROTECTED]",
+                                       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 <[EMAIL PROTECTED]>
+ *
+ * VersatileBrowser uses ColResizeBrowser, written by Greg Ercolano
+ * ColResizeBrowser (C) Greg Ercolano <[EMAIL PROTECTED]>
+ * 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 <[EMAIL PROTECTED]>
+ * Copyright (C) 2007  Miriam Ruiz <[EMAIL PROTECTED]>
  *
  * 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 <[EMAIL PROTECTED]>
+ * Copyright (C) 2007  Miriam Ruiz <[EMAIL PROTECTED]>
  *
  * 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 <[EMAIL PROTECTED]>
+ * Copyright (C) 2007, 2008  Miriam Ruiz <[EMAIL PROTECTED]>
+ *
+ * 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(_("@[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@[EMAIL PROTECTED]@[EMAIL PROTECTED]@[EMAIL PROTECTED]@[EMAIL 
PROTECTED]"));
+       }
+       else
+       {
+               ui.ResultsBrowser->column_widths(widths_without_popcon);
+               // tab delimited columns with colors
+               ui.ResultsBrowser->add(_("@[EMAIL PROTECTED]@[EMAIL 
PROTECTED]@[EMAIL PROTECTED]@[EMAIL PROTECTED]"));
+       }
+}
+
+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!

_______________________________________________
Pkg-games-commits mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/pkg-games-commits

Reply via email to