]> git.lyx.org Git - features.git/commitdiff
The Gtk patch.
authorLars Gullik Bjønnes <larsbj@gullik.org>
Tue, 2 Sep 2003 10:29:05 +0000 (10:29 +0000)
committerLars Gullik Bjønnes <larsbj@gullik.org>
Tue, 2 Sep 2003 10:29:05 +0000 (10:29 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@7632 a592a061-630c-0410-9148-cb99ea01b6c8

54 files changed:
configure.ac
po/POTFILES.in
src/Makefile.am
src/frontends/Makefile.am
src/frontends/gtk/Alert_pimpl.C [new file with mode: 0644]
src/frontends/gtk/ChangeLog [new file with mode: 0644]
src/frontends/gtk/Dialogs.C [new file with mode: 0644]
src/frontends/gtk/FileDialog.C [new file with mode: 0644]
src/frontends/gtk/FileDialogPrivate.C [new file with mode: 0644]
src/frontends/gtk/FileDialogPrivate.h [new file with mode: 0644]
src/frontends/gtk/GAboutlyx.C [new file with mode: 0644]
src/frontends/gtk/GAboutlyx.h [new file with mode: 0644]
src/frontends/gtk/GBC.C [new file with mode: 0644]
src/frontends/gtk/GBC.h [new file with mode: 0644]
src/frontends/gtk/GLyXKeySym.C [new file with mode: 0644]
src/frontends/gtk/GLyXKeySym.h [new file with mode: 0644]
src/frontends/gtk/GMenubar.C [new file with mode: 0644]
src/frontends/gtk/GMenubar.h [new file with mode: 0644]
src/frontends/gtk/GMiniBuffer.C [new file with mode: 0644]
src/frontends/gtk/GMiniBuffer.h [new file with mode: 0644]
src/frontends/gtk/GPainter.C [new file with mode: 0644]
src/frontends/gtk/GPainter.h [new file with mode: 0644]
src/frontends/gtk/GPrint.C [new file with mode: 0644]
src/frontends/gtk/GPrint.h [new file with mode: 0644]
src/frontends/gtk/GScreen.C [new file with mode: 0644]
src/frontends/gtk/GScreen.h [new file with mode: 0644]
src/frontends/gtk/GText.C [new file with mode: 0644]
src/frontends/gtk/GText.h [new file with mode: 0644]
src/frontends/gtk/GTimeout.C [new file with mode: 0644]
src/frontends/gtk/GTimeout.h [new file with mode: 0644]
src/frontends/gtk/GToolbar.C [new file with mode: 0644]
src/frontends/gtk/GToolbar.h [new file with mode: 0644]
src/frontends/gtk/GView.C [new file with mode: 0644]
src/frontends/gtk/GView.h [new file with mode: 0644]
src/frontends/gtk/GViewBase.C [new file with mode: 0644]
src/frontends/gtk/GViewBase.h [new file with mode: 0644]
src/frontends/gtk/GWorkArea.C [new file with mode: 0644]
src/frontends/gtk/GWorkArea.h [new file with mode: 0644]
src/frontends/gtk/GtkmmX.h [new file with mode: 0644]
src/frontends/gtk/IdSc.C [new file with mode: 0644]
src/frontends/gtk/IdSc.h [new file with mode: 0644]
src/frontends/gtk/LyXKeySymFactory.C [new file with mode: 0644]
src/frontends/gtk/LyXScreenFactory.C [new file with mode: 0644]
src/frontends/gtk/Makefile.am [new file with mode: 0644]
src/frontends/gtk/WorkAreaFactory.C [new file with mode: 0644]
src/frontends/gtk/codeConvert.h [new file with mode: 0644]
src/frontends/gtk/glade/Makefile.am [new file with mode: 0644]
src/frontends/gtk/glade/aboutlyx.glade [new file with mode: 0644]
src/frontends/gtk/glade/print.glade [new file with mode: 0644]
src/frontends/gtk/glade/text.glade [new file with mode: 0644]
src/frontends/gtk/lyx_gui.C [new file with mode: 0644]
src/frontends/gtk/xftFontLoader.C [new file with mode: 0644]
src/frontends/gtk/xftFontLoader.h [new file with mode: 0644]
src/frontends/gtk/xftFontMetrics.C [new file with mode: 0644]

index 04385e51b5a81b525657cad0d73c1b5626face69..9ae83b7af5d5dce13f7a469d74bd64149d13efb7 100644 (file)
@@ -188,6 +188,19 @@ for frontend in $FRONTENDS ; do
   dnl     FRONTEND_INCLUDES="${GNOME_FRONTEND_CFLAGS}"
   dnl     FRONTEND_LIBS="@XPM_LIB@ @XFORMS_LIB@ ${GNOME_FRONTEND_LIBS}"
   dnl  ;;
+    gtk)
+         XFORMS_DO_IT_ALL
+         PKG_CHECK_MODULES(GTK_FRONTEND, gtkmm-2.0 libglademm-2.0)
+         FRONTENDS_PROGS="$FRONTENDS_PROGS lyx-gtk\$(EXEEXT)"
+         FRONTENDS_SUBDIRS="$FRONTENDS_SUBDIRS xforms gtk"
+         RPM_FRONTEND="gtk"
+         RPM_FRONTEND_DEPS='gtkmm >= 2.2.0'
+         GTKMM_VERSION=`pkg-config --modversion gtkmm-2.0`
+         LIBGLADEMM_VERSION=`pkg-config --modversion libglademm-2.0`
+         FRONTEND_INFO="    libgtkmm version:             ${GTKMM_VERSION}\n\
+    libglademm version:           ${LIBGLADEMM_VERSION}\n"
+         ;;
+
     qt)
          QT_DO_IT_ALL
          FRONTENDS_PROGS="$FRONTENDS_PROGS lyx-qt\$(EXEEXT)"
@@ -395,6 +408,8 @@ AC_CONFIG_FILES([Makefile \
        src/frontends/xforms/lyx_forms.h-tmp:src/frontends/xforms/lyx_forms.h.in \
        src/frontends/xforms/lyx_xpm.h-tmp:src/frontends/xforms/lyx_xpm.h.in \
        src/frontends/xforms/forms/Makefile \
+       src/frontends/gtk/Makefile \
+       src/frontends/gtk/glade/Makefile \
        src/frontends/qt2/Makefile \
        src/frontends/qt2/moc/Makefile \
        src/frontends/qt2/ui/Makefile \
index 4942f1d64fefe58fa02133519e3c5f3e0785a943..db0888f6ce3ffe6d334529f6182f00bc113b144e 100644 (file)
@@ -35,6 +35,8 @@ src/frontends/controllers/character.C
 src/frontends/controllers/frnt_lang.C
 src/frontends/controllers/helper_funcs.C
 src/frontends/gnome/GLog.C
+src/frontends/gtk/Dialogs.C
+src/frontends/gtk/GBC.h
 src/frontends/qt2/Alert_pimpl.C
 src/frontends/qt2/BulletsModule.C
 src/frontends/qt2/Dialogs.C
index 311fe12251d0f2945df5f7f6bc35b7b1fae876e8..649144df958c3f4a2d4dd9619fe11382edfbf00f 100644 (file)
@@ -31,7 +31,7 @@ OTHERLIBS = $(BOOST_LIBS) $(INTLLIBS) $(AIKSAURUS_LIBS) @LIBS@
 
 bin_PROGRAMS = lyx 
 noinst_PROGRAMS = $(FRONTENDS_PROGS)
-EXTRA_PROGRAMS = lyx-xforms lyx-qt
+EXTRA_PROGRAMS = lyx-xforms lyx-qt lyx-gtk
 
 lyx_xforms_LDADD = $(lyx_OBJECTS) $(LYX_PRE_LIBS) \
        frontends/xforms/libxforms.la $(LYX_POST_LIBS) $(OTHERLIBS) 
@@ -42,6 +42,10 @@ lyx_qt_LDADD = $(lyx_OBJECTS) $(LYX_PRE_LIBS) \
        frontends/qt2/libqt2.la $(LYX_POST_LIBS) $(OTHERLIBS)
 lyx_qt_SOURCES = main.C
 
+lyx_gtk_LDADD = $(lyx_OBJECTS) $(LYX_PRE_LIBS) \
+       frontends/gtk/libgtk.la $(LYX_POST_LIBS) $(OTHERLIBS)
+lyx_gtk_SOURCES = main.C
+
 lyx$(EXEEXT): $(FRONTENDS_PROGS)
        rm -f $@
        $(LN_S) $< $@
index 213ed48c092ed17ca36e36dca0c448b555d5179a..6b37652747d6408e7ecd41f9492a1578fdcd975e 100644 (file)
@@ -2,7 +2,7 @@ include $(top_srcdir)/config/common.am
 
 SUBDIRS = controllers $(FRONTENDS_SUBDIRS)
 
-DIST_SUBDIRS = controllers xforms qt2 gnome
+DIST_SUBDIRS = controllers xforms qt2 gnome gtk
 
 noinst_LTLIBRARIES = libfrontends.la
 
diff --git a/src/frontends/gtk/Alert_pimpl.C b/src/frontends/gtk/Alert_pimpl.C
new file mode 100644 (file)
index 0000000..d390339
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+ * \file Alert_pimpl.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "frontends/Alert.h"
+#include "frontends/Alert_pimpl.h"
+
+
+namespace {
+
+
+string translateShortcut(string const & str)
+{
+       string::size_type i = str.find_first_of("&");
+       if (i == string::npos || i == str.length() - 1)
+               return str;
+       string tstr = str;
+       tstr[i] = '_';
+       return tstr;
+}
+
+
+}
+
+
+void warning_pimpl(string const &, string const & message)
+{
+       Gtk::MessageDialog dlg(Glib::locale_to_utf8(message),
+                              Gtk::MESSAGE_WARNING,
+                              Gtk::BUTTONS_CLOSE, true, true);
+       dlg.run();
+}
+
+
+void error_pimpl(string const &, string const & message)
+{
+       Gtk::MessageDialog dlg(Glib::locale_to_utf8(message),
+                              Gtk::MESSAGE_ERROR,
+                              Gtk::BUTTONS_CLOSE, true, true);
+       dlg.run();
+}
+
+
+void information_pimpl(string const &, string const & message)
+{
+       Gtk::MessageDialog dlg(Glib::locale_to_utf8(message),
+                              Gtk::MESSAGE_INFO,
+                              Gtk::BUTTONS_CLOSE, true, true);
+       dlg.run();
+}
+
+
+int prompt_pimpl(string const &, string const & question,
+                int defaultButton, int /*escapeButton*/,
+                string const & b1, string const & b2, string const & b3)
+{
+       Glib::ustring gb1 = Glib::locale_to_utf8(translateShortcut(b1));
+       Glib::ustring gb2 = Glib::locale_to_utf8(translateShortcut(b2));
+       Glib::ustring gb3;
+       if (!b3.empty())
+               gb3 = Glib::locale_to_utf8(translateShortcut(b3));
+       Gtk::MessageDialog dlg(Glib::locale_to_utf8(question),
+                              Gtk::MESSAGE_QUESTION,
+                              Gtk::BUTTONS_NONE, true, true);
+       dlg.add_button(gb1, 0);
+       dlg.add_button(gb2, 1);
+       if (!b3.empty())
+               dlg.add_button(gb3, 2);
+       dlg.set_default_response(defaultButton);
+       return dlg.run();
+}
+
+
+std::pair<bool, string> const askForText_pimpl(string const & msg,
+                                              string const & dflt)
+{
+       Gtk::MessageDialog dlg(Glib::locale_to_utf8(msg),
+                              Gtk::MESSAGE_QUESTION,
+                              Gtk::BUTTONS_OK_CANCEL,
+                              true, true);
+       Gtk::Entry entry;
+       entry.set_text(Glib::locale_to_utf8(dflt));
+       entry.set_position(-1);
+       entry.show();
+       dlg.get_vbox()->children().push_back(
+               Gtk::Box_Helpers::Element(entry));
+       int response = dlg.run();
+       if (response == Gtk::RESPONSE_OK) {
+               string str = Glib::locale_from_utf8(entry.get_text());
+               return std::make_pair<bool, string>(true, str);
+       }
+       else
+               return std::make_pair<bool, string>(false, string());
+}
diff --git a/src/frontends/gtk/ChangeLog b/src/frontends/gtk/ChangeLog
new file mode 100644 (file)
index 0000000..7b6f214
--- /dev/null
@@ -0,0 +1,3 @@
+2003-9-2 hying_caritas@163.com
+
+       * initial release
diff --git a/src/frontends/gtk/Dialogs.C b/src/frontends/gtk/Dialogs.C
new file mode 100644 (file)
index 0000000..5a22d89
--- /dev/null
@@ -0,0 +1,481 @@
+/**
+ * \file xforms/Dialogs.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Angus Leeming
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+
+#include "Dialogs.h"
+#include "Dialog.h"
+
+#include "Tooltips.h"
+
+#include "ControlAboutlyx.h"
+#include "ControlBibtex.h"
+#include "ControlBranch.h"
+#include "ControlChanges.h"
+#include "ControlCharacter.h"
+#include "ControlCitation.h"
+#include "ControlCommand.h"
+#include "ControlErrorList.h"
+#include "ControlERT.h"
+#include "ControlExternal.h"
+#include "ControlFloat.h"
+#include "ControlGraphics.h"
+#include "ControlInclude.h"
+#include "ControlLog.h"
+#include "ControlMath.h"
+#include "ControlMinipage.h"
+#include "ControlNote.h"
+#include "ControlParagraph.h"
+#include "ControlRef.h"
+#include "ControlShowFile.h"
+#include "ControlTabular.h"
+#include "ControlTabularCreate.h"
+#include "ControlTexinfo.h"
+#include "ControlToc.h"
+#include "ControlVCLog.h"
+#include "ControlWrap.h"
+
+#include "GAboutlyx.h"
+#include "GText.h"
+#include "FormBibitem.h"
+#include "FormBibtex.h"
+#include "FormBranch.h"
+#include "FormChanges.h"
+#include "FormCharacter.h"
+#include "FormCitation.h"
+#include "FormErrorList.h"
+#include "FormERT.h"
+#include "FormExternal.h"
+#include "FormFloat.h"
+#include "FormGraphics.h"
+#include "FormInclude.h"
+#include "FormLog.h"
+#include "FormMathsPanel.h"
+#include "FormMathsBitmap.h"
+#include "FormMathsDelim.h"
+#include "FormMathsMatrix.h"
+#include "FormMathsSpace.h"
+#include "FormMathsStyle.h"
+#include "FormMinipage.h"
+#include "FormNote.h"
+#include "FormParagraph.h"
+#include "FormRef.h"
+#include "FormTabular.h"
+#include "FormTexinfo.h"
+#include "FormShowFile.h"
+#include "FormTabularCreate.h"
+#include "FormToc.h"
+#include "FormUrl.h"
+#include "FormVCLog.h"
+#include "FormWrap.h"
+
+#ifdef HAVE_LIBAIKSAURUS
+#include "ControlThesaurus.h"
+#include "FormThesaurus.h"
+#endif
+
+#include "xformsBC.h"
+#include "ButtonController.h"
+
+#include "arrows.xbm"
+#include "bop.xbm"
+#include "brel.xbm"
+#include "deco.xbm"
+#include "dots.xbm"
+#include "greek.xbm"
+#include "misc.xbm"
+#include "varsz.xbm"
+
+#include "ams_misc.xbm"
+#include "ams_arrows.xbm"
+#include "ams_rel.xbm"
+#include "ams_nrel.xbm"
+#include "ams_ops.xbm"
+
+#include <vector>
+
+
+namespace {
+
+FormMathsBitmap * createFormBitmap(Dialog & parent, string const & title,
+                                  char const * const * data, int size)
+{
+       char const * const * const end = data + size;
+       return new FormMathsBitmap(parent, title, std::vector<string>(data, end));
+}
+
+
+char const * const dialognames[] = { "aboutlyx", "bibitem", "bibtex", "branch", "changes",
+"character", "citation", "error", "errorlist" , "ert", "external", "file",
+"float", "graphics", "include", "index", "label", "latexlog", "mathpanel",
+"mathaccents", "matharrows", "mathoperators", "mathrelations", "mathgreek",
+"mathmisc", "mathdots", "mathbigoperators", "mathamsmisc",
+"mathamsarrows", "mathamsrelations", "mathamsnegatedrelations", "mathamsoperators",
+"mathdelimiter", "mathmatrix", "mathspace", "mathstyle",
+"minipage", "note", "paragraph", "ref", "tabular", "tabularcreate", "texinfo",
+
+#ifdef HAVE_LIBAIKSAURUS
+"thesaurus",
+#endif
+
+"toc", "url", "vclog", "wrap" };
+
+char const * const * const end_dialognames =
+       dialognames + (sizeof(dialognames) / sizeof(char *));
+
+struct cmpCStr {
+       cmpCStr(char const * name) : name_(name) {}
+       bool operator()(char const * other) {
+               return strcmp(other, name_) == 0;
+       }
+private:
+       char const * name_;
+};
+
+} // namespace anon
+
+
+bool Dialogs::isValidName(string const & name) const
+{
+       return std::find_if(dialognames, end_dialognames,
+                           cmpCStr(name.c_str())) != end_dialognames;
+}
+
+
+Dialog * Dialogs::build(string const & name)
+{
+       if (!isValidName(name))
+               return 0;
+
+       Dialog * dialog = new Dialog(lyxview_, name);
+       dialog->bc().view(new xformsBC(dialog->bc()));
+
+       if (name == "aboutlyx") {
+               dialog->bc().view(new GBC(dialog->bc()));
+               dialog->setController(new ControlAboutlyx(*dialog));
+               dialog->setView(new GAboutlyx(*dialog));
+               dialog->bc().bp(new OkCancelPolicy);
+       } else if (name == "bibitem") {
+               dialog->setController(new ControlCommand(*dialog, name));
+               dialog->setView(new FormBibitem(*dialog));
+               dialog->bc().bp(new OkCancelReadOnlyPolicy);
+       } else if (name == "bibtex") {
+               dialog->setController(new ControlBibtex(*dialog));
+               dialog->setView(new FormBibtex(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "character") {
+               dialog->setController(new ControlCharacter(*dialog));
+               dialog->setView(new FormCharacter(*dialog));
+               dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
+       } else if (name == "changes") {
+               dialog->setController(new ControlChanges(*dialog));
+               dialog->setView(new FormChanges(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "citation") {
+               dialog->setController(new ControlCitation(*dialog));
+               dialog->setView(new FormCitation(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "errorlist") {
+               dialog->setController(new ControlErrorList(*dialog));
+               dialog->setView(new FormErrorList(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "ert") {
+               dialog->setController(new ControlERT(*dialog));
+               dialog->setView(new FormERT(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "external") {
+               dialog->setController(new ControlExternal(*dialog));
+               dialog->setView(new FormExternal(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "file") {
+               dialog->setController(new ControlShowFile(*dialog));
+               dialog->setView(new FormShowFile(*dialog));
+               dialog->bc().bp(new OkCancelPolicy);
+       } else if (name == "float") {
+               dialog->setController(new ControlFloat(*dialog));
+               dialog->setView(new FormFloat(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "graphics") {
+               dialog->setController(new ControlGraphics(*dialog));
+               dialog->setView(new FormGraphics(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "include") {
+               dialog->setController(new ControlInclude(*dialog));
+               dialog->setView(new FormInclude(*dialog));
+               dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
+       } else if (name == "index") {
+               dialog->bc().view(new GBC(dialog->bc()));
+               dialog->setController(new ControlCommand(*dialog, name));
+               dialog->setView(new GText(*dialog,
+                                         _("Index"), _("Keyword:|#K")));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "label") {
+               dialog->bc().view(new GBC(dialog->bc()));
+               dialog->setController(new ControlCommand(*dialog, name));
+               dialog->setView(new GText(*dialog,
+                                         _("Label"), _("Label:|#L")));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "latexlog") {
+               dialog->setController(new ControlLog(*dialog));
+               dialog->setView(new FormLog(*dialog));
+               dialog->bc().bp(new OkCancelPolicy);
+
+       } else if (name == "mathpanel") {
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(new FormMathsPanel(*dialog));
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathaccents") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("Maths Decorations & Accents"),
+                                        latex_deco, nr_latex_deco);
+               bitmap->addBitmap(
+                       BitmapStore(12, 3, 4, deco1_width, deco1_height, deco1_bits, true));
+               bitmap->addBitmap(
+                       BitmapStore(10, 4, 3, deco2_width, deco2_height, deco2_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "matharrows") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("Arrows"), latex_arrow, nr_latex_arrow);
+               bitmap->addBitmap(
+                       BitmapStore(20, 5, 4, arrow_width,  arrow_height,  arrow_bits, true));
+               bitmap->addBitmap(
+                       BitmapStore(7,  2, 4, larrow_width, larrow_height, larrow_bits, false));
+               bitmap->addBitmap(
+                       BitmapStore(4,  2, 2, darrow_width,  darrow_height, darrow_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathoperators") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("Binary Ops"),
+                                        latex_bop, nr_latex_bop);
+               bitmap->addBitmap(
+                       BitmapStore(31, 4, 8, bop_width, bop_height, bop_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathrelations") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("Binary Relations"),
+                                        latex_brel, nr_latex_brel);
+               bitmap->addBitmap(
+                       BitmapStore(35, 4, 9, brel_width, brel_height, brel_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathgreek") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("Greek"),
+                                        latex_greek, nr_latex_greek);
+               bitmap->addBitmap(
+                       BitmapStore(11, 6, 2, Greek_width, Greek_height, Greek_bits, true));
+               bitmap->addBitmap(
+                       BitmapStore(28, 7, 4, greek_width, greek_height, greek_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathmisc") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("Misc"),
+                                        latex_misc, nr_latex_misc);
+               bitmap->addBitmap(
+                       BitmapStore(29, 5, 6, misc_width, misc_height, misc_bits, true));
+               bitmap->addBitmap(
+                       BitmapStore(5, 5, 1, misc4_width, misc4_height, misc4_bits, true));
+               bitmap->addBitmap(
+                       BitmapStore(6, 3, 2, misc2_width, misc2_height, misc2_bits, false));
+               bitmap->addBitmap(
+                       BitmapStore(4, 2, 2, misc3_width, misc3_height, misc3_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathdots") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("Dots"),
+                                        latex_dots, nr_latex_dots);
+               bitmap->addBitmap(
+                       BitmapStore(4, 4, 1, dots_width, dots_height, dots_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathbigoperators") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("Big Operators"),
+                                        latex_varsz, nr_latex_varsz);
+               bitmap->addBitmap(
+                       BitmapStore(14, 3, 5, varsz_width, varsz_height, varsz_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathamsmisc") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("AMS Misc"),
+                                        latex_ams_misc, nr_latex_ams_misc);
+               bitmap->addBitmap(
+                       BitmapStore(9, 5, 2, ams1_width, ams1_height, ams1_bits, true));
+               bitmap->addBitmap(
+                       BitmapStore(26, 3, 9, ams7_width, ams7_height, ams7_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathamsarrows") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("AMS Arrows"),
+                                        latex_ams_arrows, nr_latex_ams_arrows);
+               bitmap->addBitmap(
+                       BitmapStore(32, 3, 11, ams2_width, ams2_height, ams2_bits, true));
+               bitmap->addBitmap(
+                       BitmapStore(6, 3, 2, ams3_width, ams3_height, ams3_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathamsrelations") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("AMS Relations"),
+                                        latex_ams_rel, nr_latex_ams_rel);
+               bitmap->addBitmap(
+                       BitmapStore(66, 6, 11, ams_rel_width, ams_rel_height, ams_rel_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathamsnegatedrelations") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("AMS Negated Rel"),
+                                        latex_ams_nrel, nr_latex_ams_nrel);
+               bitmap->addBitmap(
+                       BitmapStore(51, 6, 9, ams_nrel_width, ams_nrel_height, ams_nrel_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathamsoperators") {
+               FormMathsBitmap * bitmap =
+                       createFormBitmap(*dialog, _("AMS Operators"),
+                                        latex_ams_ops, nr_latex_ams_ops);
+               bitmap->addBitmap(
+                       BitmapStore(23, 3, 8, ams_ops_width, ams_ops_height, ams_ops_bits, true));
+
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(bitmap);
+               dialog->bc().bp(new IgnorantPolicy);
+
+       } else if (name == "mathdelimiter") {
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(new FormMathsDelim(*dialog));
+               dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
+       } else if (name == "mathmatrix") {
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(new FormMathsMatrix(*dialog));
+               dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
+       } else if (name == "mathspace") {
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(new FormMathsSpace(*dialog));
+               dialog->bc().bp(new IgnorantPolicy);
+       } else if (name == "mathstyle") {
+               dialog->setController(new ControlMath(*dialog));
+               dialog->setView(new FormMathsStyle(*dialog));
+               dialog->bc().bp(new IgnorantPolicy);
+       } else if (name == "minipage") {
+               dialog->setController(new ControlMinipage(*dialog));
+               dialog->setView(new FormMinipage(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "note") {
+               dialog->setController(new ControlNote(*dialog));
+               dialog->setView(new FormNote(*dialog));
+               dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
+       } else if (name == "branch") {
+               dialog->setController(new ControlBranch(*dialog));
+               dialog->setView(new FormBranch(*dialog));
+               dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
+       } else if (name == "paragraph") {
+               dialog->setController(new ControlParagraph(*dialog));
+               dialog->setView(new FormParagraph(*dialog));
+               dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
+       } else if (name == "ref") {
+               dialog->setController(new ControlRef(*dialog));
+               dialog->setView(new FormRef(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "tabular") {
+               dialog->setController(new ControlTabular(*dialog));
+               dialog->setView(new FormTabular(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "tabularcreate") {
+               dialog->setController(new ControlTabularCreate(*dialog));
+               dialog->setView(new FormTabularCreate(*dialog));
+               dialog->bc().bp(new IgnorantPolicy);
+       } else if (name == "texinfo") {
+               dialog->setController(new ControlTexinfo(*dialog));
+               dialog->setView(new FormTexinfo(*dialog));
+               dialog->bc().bp(new OkCancelPolicy);
+#ifdef HAVE_LIBAIKSAURUS
+       } else if (name == "thesaurus") {
+               dialog->setController(new ControlThesaurus(*dialog));
+               dialog->setView(new FormThesaurus(*dialog));
+               dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
+#endif
+       } else if (name == "toc") {
+               dialog->setController(new ControlToc(*dialog));
+               dialog->setView(new FormToc(*dialog));
+               dialog->bc().bp(new OkCancelPolicy);
+       } else if (name == "url") {
+               dialog->setController(new ControlCommand(*dialog, name));
+               dialog->setView(new FormUrl(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       } else if (name == "vclog") {
+               dialog->setController(new ControlVCLog(*dialog));
+               dialog->setView(new FormVCLog(*dialog));
+               dialog->bc().bp(new OkCancelPolicy);
+       } else if (name == "wrap") {
+               dialog->setController(new ControlWrap(*dialog));
+               dialog->setView(new FormWrap(*dialog));
+               dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
+       }
+
+       return dialog;
+}
+
+
+void Dialogs::toggleTooltips()
+{
+       Tooltips::toggleEnabled();
+}
+
+
+/// Are the tooltips on or off?
+bool Dialogs::tooltipsEnabled()
+{
+       return Tooltips::enabled();
+}
diff --git a/src/frontends/gtk/FileDialog.C b/src/frontends/gtk/FileDialog.C
new file mode 100644 (file)
index 0000000..99a5f08
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * \file FileDialog.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "FileDialogPrivate.h"
+
+
+FileDialog::FileDialog(string const & title,
+                      kb_action action,
+                      Button b1,
+                      Button b2)
+{
+       private_ = new FileDialog::Private(title, action, b1, b2);
+}
+
+
+FileDialog::~FileDialog()
+{
+       delete private_;
+}
+
+
+FileDialog::Result const FileDialog::open(string const & path,
+                                         string const & mask,
+                                         string const & suggested)
+{
+       return private_->open(path, mask, suggested);
+}
+
+               
+FileDialog::Result const FileDialog::opendir(string const & path,
+                                            string const & suggested)
+{
+       return private_->opendir(path, suggested);
+}
+
+
+FileDialog::Result const FileDialog::save(string const & path,
+                                         string const & mask,
+                                         string const & suggested)
+{
+       return private_->save(path, mask, suggested);
+}
diff --git a/src/frontends/gtk/FileDialogPrivate.C b/src/frontends/gtk/FileDialogPrivate.C
new file mode 100644 (file)
index 0000000..096f018
--- /dev/null
@@ -0,0 +1,99 @@
+/**
+ * \file FileDialogPrivate.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "LString.h"
+
+#include "FileDialogPrivate.h"
+
+
+FileDialog::Private::Private(string const & title,
+                            kb_action action,
+                            FileDialog::Button b1,
+                            FileDialog::Button b2) :
+       action_(action)
+{
+       fileSelection_.set_title(title);
+       fileSelection_.get_button_area()->children().push_back(
+               Gtk::Box_Helpers::Element(button1_));
+       fileSelection_.get_button_area()->children().push_back(
+               Gtk::Box_Helpers::Element(button2_));
+       button1_.signal_clicked().connect(
+               SigC::slot(*this, &FileDialog::Private::onButton1Clicked));
+       button2_.signal_clicked().connect(
+               SigC::slot(*this, &FileDialog::Private::onButton2Clicked));
+       if (!b1.first.empty() && !b1.second.empty()) {
+               string::size_type pos = b1.first.find('|');
+               button1_.set_label(
+                       Glib::locale_to_utf8(b1.first.substr(0, pos)));
+               dir1_ = b1.second;
+               button1_.show();
+       }
+       if (!b2.first.empty() && !b2.second.empty()) {
+               string::size_type pos = b2.first.find('|');
+               button2_.set_label(
+                       Glib::locale_to_utf8(b2.first.substr(0, pos)));
+               dir2_ = b2.second;
+               button2_.show();
+       }
+}
+
+
+void FileDialog::Private::onButton1Clicked()
+{
+       fileSelection_.set_filename(dir1_);
+}
+
+
+void FileDialog::Private::onButton2Clicked()
+{
+       fileSelection_.set_filename(dir2_);
+}
+
+
+FileDialog::Result const FileDialog::Private::open(string const & path,
+                                                  string const & /*mask*/,
+                                                  string const & /*suggested*/)
+{
+       fileSelection_.set_filename(path);
+       fileSelection_.get_file_list()->get_parent()->show();
+       Result result;
+       result.first = FileDialog::Chosen;
+       if (fileSelection_.run() == Gtk::RESPONSE_OK)
+               result.second = fileSelection_.get_filename();
+       else
+               result.second = string();
+       return result;
+}
+
+
+FileDialog::Result const FileDialog::Private::opendir(string const & path,
+                                                     string const & /*suggested*/)
+{
+       fileSelection_.set_filename(path);
+       fileSelection_.get_file_list()->get_parent()->hide();
+       Result result;
+       result.first = FileDialog::Chosen;
+       if (fileSelection_.run() == Gtk::RESPONSE_OK)
+               result.second = fileSelection_.get_filename();
+       else
+               result.second = string();
+       return result;
+}
+
+
+FileDialog::Result const FileDialog::Private::save(string const & path,
+                                                  string const & mask,
+                                                  string const & suggested)
+{
+       return open(path, mask, suggested);
+}
diff --git a/src/frontends/gtk/FileDialogPrivate.h b/src/frontends/gtk/FileDialogPrivate.h
new file mode 100644 (file)
index 0000000..51d4777
--- /dev/null
@@ -0,0 +1,45 @@
+// -*- C++ -*-
+/**
+ * \file FileDialogPrivate.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef FILE_DIALOG_PRIVATE_H
+#define FILE_DIALOG_PRIVATE_H
+
+#include <gtkmm.h>
+#include "frontends/FileDialog.h"
+
+class FileDialog::Private : public SigC::Object
+{
+public:
+       Private(string const & title,
+               kb_action action,
+               FileDialog::Button b1, FileDialog::Button b2);
+       FileDialog::Result const open(string const & path,
+                                     string const & mask,
+                                     string const & suggested);
+       FileDialog::Result const opendir(string const & path,
+                                        string const & suggested);
+
+       FileDialog::Result const save(string const & path,
+                                     string const & mask,
+                                     string const & suggested);
+
+private:
+       void onButton1Clicked();
+       void onButton2Clicked();
+       Gtk::FileSelection fileSelection_;
+       Gtk::Button button1_;
+       Gtk::Button button2_;
+       string dir1_;
+       string dir2_;
+       kb_action action_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GAboutlyx.C b/src/frontends/gtk/GAboutlyx.C
new file mode 100644 (file)
index 0000000..9967cc2
--- /dev/null
@@ -0,0 +1,168 @@
+/**
+ * \file GAboutlyx.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include <libglademm.h>
+#include <sstream>
+
+#include "ControlAboutlyx.h"
+#include "GAboutlyx.h"
+#include "support/filetools.h"
+#include "version.h"
+
+namespace {
+
+enum TranslateState {NORMAL, BEGIN, IN_AT, IN_BOLD, IN_ITALIC};
+
+
+Glib::ustring translateMarkup(Glib::ustring const & lyxMarkup)
+{
+       Glib::ustring::const_iterator it = lyxMarkup.begin();
+       Glib::ustring pangoMarkup;
+       TranslateState state = BEGIN;
+       for (; it != lyxMarkup.end(); it++) {
+               switch (state) {
+               case BEGIN:
+                       switch (*it) {
+                       case '@':
+                               state = IN_AT;
+                               break;
+                       case '\n':
+                               state = BEGIN;
+                               pangoMarkup.push_back('\n');
+                               break;
+                       default:
+                               state = NORMAL;
+                               pangoMarkup.push_back(*it);
+                               break;
+                       }
+                       break;
+               case IN_AT:
+                       switch (*it) {
+                       case 'b':
+                               state = IN_BOLD;
+                               pangoMarkup += "<b>";
+                               break;
+                       case 'i':
+                               state = IN_ITALIC;
+                               pangoMarkup += "<i>";
+                               break;
+                       case '\n':
+                               state = BEGIN;
+                               pangoMarkup.push_back('@');
+                               pangoMarkup.push_back('\n');
+                               break;
+                       default:
+                               state = NORMAL;
+                               pangoMarkup.push_back('@');
+                               pangoMarkup.push_back(*it);
+                       }
+                       break;
+               case IN_BOLD:
+                       switch (*it) {
+                       case '\n':
+                               state = BEGIN;
+                               pangoMarkup += "</b>\n";
+                               break;
+                       default:
+                               pangoMarkup.push_back(*it);
+                       }
+                       break;
+               case IN_ITALIC:
+                       switch (*it) {
+                       case '\n':
+                               state = BEGIN;  
+                               pangoMarkup += "</i>\n";
+                               break;
+                       default:
+                               pangoMarkup.push_back(*it);
+                       }
+                       break;
+               case NORMAL:
+                       switch (*it) {
+                       case '\n':
+                               state = BEGIN;
+                               pangoMarkup.push_back('\n');
+                               break;
+                       default:
+                               pangoMarkup.push_back(*it);
+                       }
+               }
+               switch (*it) {
+               case '&':
+                       pangoMarkup += "amp;";
+                       break;
+               case '<':
+                       pangoMarkup.erase(--(pangoMarkup.end()));
+                       pangoMarkup += "&lt;";
+                       break;
+               case '>':
+                       pangoMarkup.erase(--(pangoMarkup.end()));
+                       pangoMarkup += "&gt;";
+                       break;
+               default:
+                       break;
+               }
+       }
+       switch (state) {
+       case IN_AT:
+               pangoMarkup.push_back('@');
+               break;
+       case IN_ITALIC:
+               pangoMarkup += "</i>";
+               break;
+       case IN_BOLD:
+               pangoMarkup += "</b>";
+               break;
+       default:
+               break;
+       }
+       return pangoMarkup;
+}
+
+
+}
+
+
+GAboutlyx::GAboutlyx(Dialog & parent)
+       : GViewCB<ControlAboutlyx, GViewGladeB>(parent, "About LyX")
+{
+}
+
+
+void GAboutlyx::doBuild()
+{
+       string const gladeName =
+               lyx::support::LibFileSearch("glade", "aboutlyx", "glade");
+       xml_ = Gnome::Glade::Xml::create(gladeName);
+       Gtk::Label * version;
+       Gtk::Label * credits;
+       Gtk::Label * license;
+       xml_->get_widget("version", version);
+       xml_->get_widget("credits", credits);
+       xml_->get_widget("license", license);
+       std::ostringstream vs;
+       vs << controller().getVersion()
+          << std::endl << lyx_version_info;
+       version->set_text(Glib::locale_to_utf8(vs.str()));
+       std::ostringstream crs;
+       controller().getCredits(crs);
+       credits->set_markup(translateMarkup(Glib::locale_to_utf8(crs.str())));
+       std::ostringstream ls;
+       ls << controller().getCopyright() << "\n\n"
+          << controller().getLicense() << "\n\n"
+          << controller().getDisclaimer();
+       license->set_text(Glib::locale_to_utf8(ls.str()));
+       Gtk::Button * btn;
+       xml_->get_widget("close_button", btn);
+       btn->signal_clicked().connect(SigC::slot(*this, &GViewBase::onCancel));
+}
diff --git a/src/frontends/gtk/GAboutlyx.h b/src/frontends/gtk/GAboutlyx.h
new file mode 100644 (file)
index 0000000..f0a85d4
--- /dev/null
@@ -0,0 +1,29 @@
+// -*- C++ -*-
+/**
+ * \file GAboutlyx.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GABOUTLYX_H
+#define GABOUTLYX_H
+
+#include "GViewBase.h"
+
+class ControlAboutlyx;
+
+class GAboutlyx : public GViewCB<ControlAboutlyx, GViewGladeB>
+{
+public:
+       GAboutlyx(Dialog &);
+private:
+       virtual void apply() {}
+       virtual void update() {}
+       virtual void doBuild();
+};
+
+#endif
diff --git a/src/frontends/gtk/GBC.C b/src/frontends/gtk/GBC.C
new file mode 100644 (file)
index 0000000..9a9992e
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * \file GBC.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "GBC.h"
+
+
+GBC::GBC(ButtonController const & parent,
+        string const & cancel, string const & close)
+       : GuiBC<Gtk::Button, Gtk::Widget>(parent, cancel, close)
+{
+}
+
+
+void GBC::setButtonEnabled(Gtk::Button * btn, bool enabled) const
+{
+       btn->set_sensitive(enabled);
+}
+
+
+void GBC::setWidgetEnabled(Gtk::Widget * widget, bool enabled) const
+{
+       widget->set_sensitive(enabled);
+}
+
+
+void GBC::setButtonLabel(Gtk::Button * btn, string const & label) const
+{
+       btn->set_label(Glib::locale_to_utf8(label));
+}
diff --git a/src/frontends/gtk/GBC.h b/src/frontends/gtk/GBC.h
new file mode 100644 (file)
index 0000000..a85d079
--- /dev/null
@@ -0,0 +1,39 @@
+// -*- C++ -*-
+/**
+ * \file GBC.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GBUTTONCONTROLLER_H
+#define GBUTTONCONTROLLER_H
+
+#include <gtkmm.h>
+
+#include "ButtonController.h"
+#include "BCView.h"
+#include "LString.h"
+#include "gettext.h"
+
+class GBC : public GuiBC<Gtk::Button, Gtk::Widget>
+{
+public:
+       GBC(ButtonController const & parent,
+           string const & cancel = _("Cancel"),
+           string const & close = _("Close"));
+private:
+       /// Updates the button sensitivity (enabled/disabled)
+       void setButtonEnabled(Gtk::Button *, bool enabled) const;
+
+       /// Updates the widget sensitivity (enabled/disabled)
+       void setWidgetEnabled(Gtk::Widget *, bool enabled) const;
+
+       /// Set the label on the button
+       void setButtonLabel(Gtk::Button *, string const & label) const;
+};
+
+#endif
diff --git a/src/frontends/gtk/GLyXKeySym.C b/src/frontends/gtk/GLyXKeySym.C
new file mode 100644 (file)
index 0000000..17f80bd
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ * \file GLyXKeySym.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include <gdk/gdkkeysyms.h>
+#include "GLyXKeySym.h"
+
+
+GLyXKeySym::GLyXKeySym() : keyval_(GDK_VoidSymbol)
+{
+}
+
+
+GLyXKeySym::GLyXKeySym(unsigned int keyval) : keyval_(keyval)
+{
+}
+
+
+void GLyXKeySym::setKeyval(unsigned int keyval)
+{
+       keyval_ = keyval;
+}
+
+
+void GLyXKeySym::init(string const & symbolname)
+{
+       keyval_ = gdk_keyval_from_name(symbolname.c_str());
+}
+
+
+bool GLyXKeySym::isOK() const
+{
+       return keyval_ != GDK_VoidSymbol;
+}
+
+
+bool GLyXKeySym::isModifier() const
+{
+       return ((keyval_ >= GDK_Shift_L && keyval_ <= GDK_Hyper_R)
+               || keyval_ == GDK_Mode_switch || keyval_ == 0);
+}
+
+
+string GLyXKeySym::getSymbolName() const
+{
+       const char * name = gdk_keyval_name(keyval_);
+       return name ? name : string();
+}
+
+
+char GLyXKeySym::getISOEncoded(string const & /*encoding*/) const
+{
+       if (keyval_ == GDK_VoidSymbol)
+               return 0;
+
+       unsigned int c = keyval_;
+
+       switch (c & 0x0000FF00) {
+               // latin 1 byte 3 = 0
+       case 0x00000000: break;
+               // latin 2 byte 3 = 1
+       case 0x00000100:
+               // latin 3 byte 3 = 2
+       case 0x00000200:
+               // latin 4 byte 3 = 3
+       case 0x00000300:
+               // cyrillic KOI8 & Co
+       case 0x00000600:
+               // greek
+       case 0x00000700:
+               // latin 8 byte 3 = 18 (0x12)
+       case 0x00001200:
+               // latin 9 byte 3 = 19 (0x13)
+       case 0x00001300:
+               c &= 0x000000FF;
+               break;
+       default:
+               c = 0;
+       }
+       return c;
+}
+
+
+bool operator==(LyXKeySym const & k1, LyXKeySym const & k2)
+{
+       return static_cast<GLyXKeySym const &>(k1).getKeyval()
+               == static_cast<GLyXKeySym const &>(k2).getKeyval();
+}
diff --git a/src/frontends/gtk/GLyXKeySym.h b/src/frontends/gtk/GLyXKeySym.h
new file mode 100644 (file)
index 0000000..db650c4
--- /dev/null
@@ -0,0 +1,35 @@
+// -*- C++ -*-
+/**
+ * \file GLyXKeySym.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GLYX_KEYSYM_H
+#define GLYX_KEYSYM_H
+
+#include "LString.h"
+#include "frontends/LyXKeySym.h"
+
+class GLyXKeySym : public LyXKeySym
+{
+public:
+       GLyXKeySym();
+       GLyXKeySym(unsigned int keyval);
+       void setKeyval(unsigned int keyval);
+       unsigned int getKeyval() const { return keyval_; }
+       virtual void init(string const & symbolname);
+       virtual ~GLyXKeySym() {}
+       virtual bool isOK() const;
+       virtual bool isModifier() const;
+       virtual string getSymbolName() const;
+       virtual char getISOEncoded(string const & encoding) const;
+private:
+       unsigned int keyval_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GMenubar.C b/src/frontends/gtk/GMenubar.C
new file mode 100644 (file)
index 0000000..a5baaca
--- /dev/null
@@ -0,0 +1,228 @@
+/**
+ * \file GMenubar.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "GMenubar.h"
+#include "GView.h"
+#include "debug.h"
+#include "lyxfunc.h"
+
+namespace
+{
+
+class LyxMenu : public Gtk::Menu
+{
+public:
+       LyxMenu() { menu_.reset(new ::Menu); }
+
+       ::Menu& getBackMenu() { return *menu_.get(); }
+
+       void clearBackMenu() { menu_.reset(new ::Menu); }
+private:
+       std::auto_ptr< ::Menu > menu_;
+};
+
+
+Glib::ustring labelTrans(string const & label, string const & shortcut)
+{
+       string labelN = label;
+       string::size_type i = label.find(shortcut);
+       if (i == string::npos)
+               return Glib::locale_to_utf8(label);
+       labelN.insert(i, "_");
+       return Glib::locale_to_utf8(labelN);
+}
+
+
+void ClearMenu(Gtk::MenuShell * menu)
+{
+       Gtk::Menu_Helpers::MenuList::iterator m, end;
+       m = menu->items().begin();
+       end = menu->items().end();
+       Gtk::Menu * subMenu;
+       for (; m != end; ++m) {
+               if ((subMenu = m->get_submenu()) != 0) {
+                       ClearMenu(subMenu);
+                       delete subMenu;
+               }
+       }
+       menu->items().clear();
+}
+
+
+}
+
+
+GMenubar::GMenubar(LyXView *lyxView, MenuBackend const & /*menuBackend*/) :
+       view_(lyxView)
+{
+       GView * gview = static_cast<GView*>(lyxView);
+       Gtk::VBox& vbox = gview->getVBox();
+       Menu const & menu = menubackend.getMenubar();
+       Menu::const_iterator i = menu.begin();
+       Menu::const_iterator end = menu.end();
+       for (; i != end; ++i) {
+               if (i->kind() != MenuItem::Submenu) {
+                       lyxerr << "ERROR: GMenubar::createMenubar:"
+                               " only submenus can appear in a menubar"
+                              << std::endl;
+                       continue;
+               }
+               Gtk::Menu * gmenu = new LyxMenu;
+               menubar_.items().push_back(
+                       Gtk::Menu_Helpers::MenuElem(
+                               labelTrans(i->label(), i->shortcut()),
+                               *gmenu));
+               menubar_.items().back().signal_activate().connect(
+                       SigC::bind(SigC::slot(*this, &GMenubar::onSubMenuActivate), &(*i),
+                                  &menubar_.items().back()));
+               mainMenuNames_.push_back(i->submenuname());
+       }
+       menubar_.show();
+       vbox.children().push_back(Gtk::Box_Helpers::Element(menubar_,
+                                                           Gtk::PACK_SHRINK));
+}
+
+
+GMenubar::~GMenubar()
+{
+       ClearMenu(&menubar_);
+}
+
+
+void GMenubar::update()
+{
+}
+
+
+void GMenubar::openByName(string const & name)
+{
+       Glib::ustring uname = Glib::locale_to_utf8(name);
+       std::vector<Glib::ustring>::iterator it =
+               std::find(mainMenuNames_.begin(), mainMenuNames_.end(),
+                         uname);
+       if (it != mainMenuNames_.end()) {
+               Gtk::MenuItem& mitem = menubar_.items()[it - mainMenuNames_.begin()];
+               mitem.select();
+               mitem.activate();
+               return;
+       }
+       lyxerr << "GMenubar::openByName: menu "
+              << name << " not found" << std::endl;
+}
+
+
+bool GMenubar::submenuDisabled(MenuItem const * item)
+{
+       Menu & from = menubackend.getMenu(item->submenuname());
+       Menu to;
+       menubackend.expand(from, to, view_);
+       Menu::const_iterator i = to.begin();
+       Menu::const_iterator end = to.end();
+       for (; i != end; ++i) {
+               switch (i->kind()) {
+               case MenuItem::Submenu:
+                       if (!submenuDisabled(&(*i)))
+                               return false;
+                       break;
+               case MenuItem::Command:
+               {
+                       FuncStatus const flag =
+                               view_->getLyXFunc().getStatus(i->action());
+                       if (!flag.disabled())
+                               return false;
+                       break;
+               }
+               default:
+                       break;
+               }
+       }
+       return true;
+}
+
+
+void GMenubar::onSubMenuActivate(MenuItem const * item,
+                                      Gtk::MenuItem * gitem)
+{
+       Gtk::Menu * gmenu = gitem->get_submenu();
+       ClearMenu(gmenu);
+       LyxMenu * lyxmenu = static_cast<LyxMenu*>(gmenu);
+       lyxmenu->clearBackMenu();
+       Menu * fmenu = &menubackend.getMenu(item->submenuname());
+       menubackend.expand(*fmenu, lyxmenu->getBackMenu(), view_);
+       Menu::const_iterator i = lyxmenu->getBackMenu().begin();
+       Menu::const_iterator end = lyxmenu->getBackMenu().end();
+       Gtk::Menu * gmenu_new;
+       for (; i != end; ++i) {
+               switch (i->kind()) {
+               case MenuItem::Submenu:
+                       gmenu_new = new LyxMenu;
+                       gmenu->items().push_back(
+                               Gtk::Menu_Helpers::MenuElem(
+                                       labelTrans(i->label(), i->shortcut()),
+                                       *gmenu_new));
+                       gmenu->items().back().signal_activate().connect(
+                               SigC::bind(SigC::slot(*this, &GMenubar::onSubMenuActivate),
+                                          &(*i),
+                                          &gmenu->items().back()));
+                       if (submenuDisabled(&(*i)))
+                               gmenu->items().back().set_sensitive(false);
+                       break;
+               case MenuItem::Command:
+               {
+                       FuncStatus const flag =
+                               view_->getLyXFunc().getStatus(i->action());
+                       bool on, off;
+                       on = flag.onoff(true);
+                       off = flag.onoff(false);
+                       
+                       if (on || off) {
+                               gmenu->items().push_back(
+                                       Gtk::Menu_Helpers::CheckMenuElem(
+                                               labelTrans(i->label(),
+                                                          i->shortcut())));
+                               Gtk::CheckMenuItem& citem = 
+                                       static_cast<Gtk::CheckMenuItem&>(
+                                               gmenu->items().back());
+                               citem.set_active(on);
+                       } else {
+                               gmenu->items().push_back(
+                                       Gtk::Menu_Helpers::MenuElem(
+                                               labelTrans(i->label(),
+                                                          i->shortcut())));
+                       }
+                       Gtk::MenuItem & item = gmenu->items().back();
+                       item.signal_activate().connect(
+                               SigC::bind(SigC::slot(*this, &GMenubar::onCommandActivate),
+                                          &(*i), &item));
+                       if (flag.disabled())
+                               item.set_sensitive(false);
+                       break;
+               }
+               case MenuItem::Separator:
+                       gmenu->items().push_back(
+                               Gtk::Menu_Helpers::SeparatorElem());
+                       break;
+               default:
+                       lyxerr << "GMenubar::create_submenu: "
+                               "this should not happen" << std::endl;
+                       break;
+               }
+       }
+}
+
+
+void GMenubar::onCommandActivate(MenuItem const * item,
+                                      Gtk::MenuItem * /*gitem*/)
+{
+       view_->getLyXFunc().dispatch(item->action(), true);
+}
diff --git a/src/frontends/gtk/GMenubar.h b/src/frontends/gtk/GMenubar.h
new file mode 100644 (file)
index 0000000..8a5f8b7
--- /dev/null
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+/**
+ * \file gtk/GMenubar.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef MENUBAR_PIMPL_H
+#define MENUBAR_PIMPL_H
+
+#include "frontends/Menubar.h"
+#include "MenuBackend.h"
+#include <vector>
+
+class LyXView;
+
+class GMenubar : public Menubar, public SigC::Object {
+public:
+       GMenubar(LyXView *, MenuBackend const &);
+       ~GMenubar();
+       void update();
+       void openByName(string const &);
+private:
+       void onCommandActivate(MenuItem const * item, Gtk::MenuItem * gitem);
+       void onSubMenuActivate(MenuItem const * item, Gtk::MenuItem * gitem);
+       bool submenuDisabled(MenuItem const * item);
+       Gtk::MenuBar menubar_;
+       LyXView * view_;
+       std::vector<Glib::ustring> mainMenuNames_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GMiniBuffer.C b/src/frontends/gtk/GMiniBuffer.C
new file mode 100644 (file)
index 0000000..892c1f7
--- /dev/null
@@ -0,0 +1,281 @@
+/**
+ * \file GMiniBuffer.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "GView.h"
+#include "GMiniBuffer.h"
+#include "debug.h"
+#include "bufferview_funcs.h"
+#include <boost/bind.hpp>
+#include <vector>
+#include "frontends/controllers/ControlCommandBuffer.h"
+
+
+GMiniBuffer::GMiniBuffer(GView * view, ControlCommandBuffer & control) :
+       controller_(control), view_(view)
+{
+       listCols_.add(listCol_);
+       listStore_ = Gtk::ListStore::create(listCols_);
+       listView_.set_model(listStore_);
+       listView_.append_column("Completions", listCol_);
+       listView_.signal_key_press_event().connect(
+               SigC::slot(*this, &GMiniBuffer::onListKeyPress));
+       listView_.signal_focus_in_event().connect(
+               SigC::slot(*this, &GMiniBuffer::onListFocusIn));
+       listView_.signal_focus_out_event().connect(
+               SigC::slot(*this, &GMiniBuffer::onFocusOut));
+       listSel_ = listView_.get_selection();
+       listSel_->signal_changed().connect(
+               SigC::slot(*this, &GMiniBuffer::onSelected));
+       listView_.show();
+       scrolledWindow_.set_policy(Gtk::POLICY_AUTOMATIC,
+                                  Gtk::POLICY_AUTOMATIC);
+       scrolledWindow_.set_size_request(300, 150);
+       scrolledWindow_.add(listView_);
+       view_->getVBox().children().push_back(
+               Gtk::Box_Helpers::Element(scrolledWindow_,
+                                         Gtk::PACK_SHRINK));
+       entry_.signal_key_press_event().connect(
+               SigC::slot(*this, &GMiniBuffer::onKeyPress));
+       entry_.signal_focus_in_event().connect(
+               SigC::slot(*this, &GMiniBuffer::onFocusIn));
+       entry_.signal_focus_out_event().connect(
+               SigC::slot(*this, &GMiniBuffer::onFocusOut));
+       entry_.signal_activate().connect(
+               SigC::slot(*this, &GMiniBuffer::onCommit));
+       entry_.show();
+       view_->getVBox().children().push_back(
+               Gtk::Box_Helpers::Element(entry_,
+                                         Gtk::PACK_SHRINK));
+       infoTimer_.reset(new Timeout(1500));
+       idleTimer_.reset(new Timeout(6000));
+       focusTimer_.reset(new Timeout(50));
+       infoCon_ = infoTimer_->timeout.connect(
+               boost::bind(&GMiniBuffer::infoTimeout, this));
+       idleCon_ = idleTimer_->timeout.connect(
+               boost::bind(&GMiniBuffer::idleTimeout, this));
+       focusTimer_->timeout.connect(
+               boost::bind(&GMiniBuffer::focusTimeout, this));
+       idleTimer_->start();
+       messageMode();
+}
+
+
+GMiniBuffer::~GMiniBuffer()
+{
+}
+
+
+void GMiniBuffer::message(string const & str)
+{
+       if (!isEditMode())
+               setInput(Glib::locale_to_utf8(str));
+}
+
+
+void GMiniBuffer::showInfo(Glib::ustring const & info, bool append)
+{
+       storedInput_ = entry_.get_text();
+       entry_.set_editable(false);
+       infoShown_ = true;
+       if (append)
+               setInput(storedInput_ + ' ' + info);
+       else
+               setInput(info);
+       infoTimer_->start();
+}
+
+
+void GMiniBuffer::onSelected()
+{
+       if (!listSel_->count_selected_rows())
+               return;
+       Gtk::TreeModel::iterator it = listSel_->get_selected();
+       Glib::ustring sel = (*it)[listCol_];
+       setInput(sel + ' ');
+}
+
+
+void GMiniBuffer::onCommit()
+{
+       controller_.dispatch(Glib::locale_from_utf8(entry_.get_text()));
+       messageMode();
+}
+
+
+bool GMiniBuffer::onListFocusIn(GdkEventFocus * /*event*/)
+{
+       if (focusTimer_->running())
+               focusTimer_->stop();
+       if (infoShown_) {
+               infoTimer_->stop();
+               infoTimeout();
+       }
+       return false;
+}
+
+
+bool GMiniBuffer::onFocusIn(GdkEventFocus * /*event*/)
+{
+       if (infoShown_) {
+               infoTimer_->stop();
+               infoTimeout();
+       }
+       if (focusTimer_->running()) {
+               focusTimer_->stop();
+               return false;
+       }
+       setInput("");
+       idleTimer_->stop();
+       return false;
+}
+
+
+bool GMiniBuffer::onFocusOut(GdkEventFocus * /*event*/)
+{
+       focusTimer_->start();
+       return false;
+}
+
+
+void GMiniBuffer::focusTimeout()
+{
+       if (infoShown_) {
+               infoTimer_->stop();
+               infoTimeout();
+       }
+       focusTimer_->stop();
+       setInput("");
+       idleTimer_->start();
+       scrolledWindow_.hide();
+}
+
+
+bool GMiniBuffer::onListKeyPress(GdkEventKey * event)
+{
+       if (infoShown_) {
+               infoTimer_->stop();
+               infoTimeout();
+       }
+       switch (event->keyval) {
+       case GDK_Escape:
+               messageMode();
+               break;
+       case GDK_Tab:
+               entry_.grab_focus();
+               setInput(entry_.get_text() + ' ');
+               break;
+       }
+       return true;
+}
+
+
+bool GMiniBuffer::onKeyPress(GdkEventKey * event)
+{
+       if (infoShown_) {
+               infoTimer_->stop();
+               infoTimeout();
+       }
+       switch (event->keyval) {
+       case GDK_Down:
+       {
+               Glib::ustring const h = 
+                       Glib::locale_to_utf8(controller_.historyDown());
+               if (h.empty())
+                       showInfo("[End of history]", false);
+               else
+                       setInput(h);
+               break;
+       }
+       case GDK_Up:
+       {
+               Glib::ustring const h = 
+                       Glib::locale_to_utf8(controller_.historyUp());
+               if (h.empty())
+                       showInfo("[Beginning of history]", false);
+               else
+                       setInput(h);
+               break;
+       }
+       case GDK_Escape:
+               messageMode();
+               break;
+       case GDK_Tab:
+       {
+               Glib::ustring new_input, input;
+               string new_input_locale;
+               input = entry_.get_text();
+               std::vector<string> comp = 
+                       controller_.completions(Glib::locale_from_utf8(input),
+                                               new_input_locale);
+               new_input = Glib::locale_to_utf8(new_input_locale);
+               if (comp.empty() && new_input == input) {
+                       showInfo("[no match]");
+                       break;
+               }
+
+               if (comp.empty()) {
+                       setInput(new_input + ' ');
+                       showInfo("[only completion]");
+                       break;
+               }
+               setInput(new_input);
+               listStore_->clear();
+               std::vector<string>::iterator it;
+               for (it = comp.begin(); it != comp.end(); ++it)
+                       (*listStore_->append())[listCol_] =
+                               Glib::locale_to_utf8(*it);
+               scrolledWindow_.show();
+               break;
+       }
+       }
+       return true;
+}
+
+
+bool GMiniBuffer::isEditMode() const
+{
+       return entry_.has_focus() || listView_.has_focus();
+}
+
+
+void GMiniBuffer::infoTimeout()
+{
+       infoShown_ = false;
+       setInput(storedInput_);
+       entry_.set_editable(true);
+}
+
+
+void GMiniBuffer::idleTimeout()
+{
+       setInput(Glib::locale_to_utf8(controller_.getCurrentState()));
+}
+
+
+void GMiniBuffer::editMode()
+{
+       entry_.grab_focus();
+}
+
+
+void GMiniBuffer::messageMode()
+{
+       view_->focusWorkArea();
+}
+
+
+void GMiniBuffer::setInput(Glib::ustring const & input)
+{
+       entry_.set_text(input);
+       entry_.set_position(-1);
+}
diff --git a/src/frontends/gtk/GMiniBuffer.h b/src/frontends/gtk/GMiniBuffer.h
new file mode 100644 (file)
index 0000000..07f68af
--- /dev/null
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+/**
+ * \file GMiniBuffer.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+
+#ifndef GMINI_BUFFER_H
+#define GMINI_BUFFER_H
+
+#include "frontends/Timeout.h"
+#include "LString.h"
+class ControlCommandBuffer;
+
+class GMiniBuffer : public SigC::Object
+{
+public:
+       GMiniBuffer(GView * view, ControlCommandBuffer & control);
+       ~GMiniBuffer();
+       void message(string const & str);
+       /// go into edit mode
+       void editMode();
+private:
+       bool onKeyPress(GdkEventKey * event);
+       bool onListKeyPress(GdkEventKey * event);
+       void onCommit();
+       bool onListFocusIn(GdkEventFocus * event);
+       bool onFocusIn(GdkEventFocus * event);
+       bool onFocusOut(GdkEventFocus * event);
+       void focusTimeout();
+       void onSelected();
+       /// Are we in edit mode?
+       bool isEditMode() const;
+       /// reset buffer to stored input text
+       void infoTimeout();
+       /// go back to "at rest" message
+       void idleTimeout();
+       /// go into message mode
+       void messageMode();
+       /// show a temporary message whilst in edit mode
+       void showInfo(Glib::ustring const & info, bool append = true);
+       void setInput(Glib::ustring const & input);
+       ControlCommandBuffer & controller_;
+       GView * view_;
+       Gtk::Entry entry_;
+       /// info timer
+       boost::scoped_ptr<Timeout> infoTimer_;
+       boost::signals::connection infoCon_;
+       /// idle timer
+       boost::scoped_ptr<Timeout> idleTimer_;
+       boost::signals::connection idleCon_;
+       Glib::ustring storedInput_;
+       /// are we showing an informational temporary message ?
+       bool infoShown_;
+       boost::scoped_ptr<Timeout> focusTimer_;
+
+       Gtk::ScrolledWindow scrolledWindow_;
+       Gtk::TreeModelColumn<Glib::ustring> listCol_;
+       Gtk::TreeModel::ColumnRecord listCols_;
+       Glib::RefPtr<Gtk::ListStore> listStore_;
+       Gtk::TreeView listView_;
+       Glib::RefPtr<Gtk::TreeSelection> listSel_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GPainter.C b/src/frontends/gtk/GPainter.C
new file mode 100644 (file)
index 0000000..c17115e
--- /dev/null
@@ -0,0 +1,272 @@
+/**
+ * \file GPainter.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "GPainter.h"
+#include "LString.h"
+#include "debug.h"
+#include "GWorkArea.h"
+#include "lyxrc.h"
+#include "encoding.h"
+#include "language.h"
+#include "xftFontLoader.h"
+#include "xformsImage.h"
+#include "frontends/font_metrics.h"
+#include "codeConvert.h"
+
+#include "support/LAssert.h"
+#include "support/lstrings.h"
+
+#include <boost/scoped_array.hpp>
+#include <X11/Xft/Xft.h>
+#include <cmath>
+
+
+GPainter::GPainter(GWorkArea & xwa)
+       : Painter(), owner_(xwa)
+{
+}
+
+
+int GPainter::paperWidth() const
+{
+       return owner_.workWidth();
+}
+
+
+int GPainter::paperHeight() const
+{
+       return owner_.workHeight();
+}
+
+
+void GPainter::setForeground(Glib::RefPtr<Gdk::GC> gc, LColor::color clr)
+{
+       Gdk::Color * gclr = owner_.getColorHandler().getGdkColor(clr);
+       gc->set_foreground(*gclr);
+}
+
+
+void GPainter::setLineParam(Glib::RefPtr<Gdk::GC> gc,
+                           line_style ls, line_width lw)
+{
+       int width;
+       Gdk::LineStyle style;
+       switch (lw) {
+       case Painter::line_thin:
+               width = 0;
+               break;
+       case Painter::line_thick:
+               width = 2;
+               break;
+       }
+
+       switch (ls) {
+       case Painter::line_solid:
+               style = Gdk::LINE_SOLID;
+               break;
+       case Painter::line_onoffdash:
+               style = Gdk::LINE_ON_OFF_DASH;
+               break;
+       }
+       gc->set_line_attributes(width, style,
+                               Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
+}
+
+
+Painter & GPainter::point(int x, int y, LColor::color c)
+{
+       setForeground(owner_.getGC(), c);
+       owner_.getPixmap()->draw_point(owner_.getGC(), x, y);
+       return *this;
+}
+
+
+Painter & GPainter::line(int x1, int y1,
+       int x2, int y2,
+       LColor::color col,
+       line_style ls,
+       line_width lw)
+{
+       setForeground(owner_.getGC(), col);
+       setLineParam(owner_.getGC(), ls, lw);
+       owner_.getPixmap()->draw_line(owner_.getGC(), x1, y1, x2, y2);
+       return *this;
+}
+
+
+Painter & GPainter::lines(int const * xp, int const * yp,
+       int np,
+       LColor::color col,
+       line_style ls,
+       line_width lw)
+{
+       setForeground(owner_.getGC(), col);
+       setLineParam(owner_.getGC(), ls, lw);
+       std::vector<Gdk::Point> points(np);
+
+       for (int i = 0; i < np; ++i) {
+               points[i].set_x(xp[i]);
+               points[i].set_y(yp[i]);
+       }
+       owner_.getPixmap()->draw_lines(owner_.getGC(), points);
+       return *this;
+}
+
+
+Painter & GPainter::rectangle(int x, int y,
+       int w, int h,
+       LColor::color col,
+       line_style ls,
+       line_width lw)
+{
+       setForeground(owner_.getGC(), col);
+       setLineParam(owner_.getGC(), ls, lw);
+       owner_.getPixmap()->draw_rectangle(owner_.getGC(), false, x, y, w, h);
+       return *this;
+}
+
+
+Painter & GPainter::fillRectangle(int x, int y,
+       int w, int h,
+       LColor::color col)
+{
+       setForeground(owner_.getGC(), col);
+       owner_.getPixmap()->draw_rectangle(owner_.getGC(), true, x, y, w, h);
+       return *this;
+}
+
+
+Painter & GPainter::fillPolygon(int const * xp, int const * yp,
+       int np, LColor::color col)
+{
+       setForeground(owner_.getGC(), col);
+       std::vector<Gdk::Point> points(np);
+
+       for (int i = 0; i < np; ++i) {
+               points[i].set_x(xp[i]);
+               points[i].set_y(yp[i]);
+       }
+       owner_.getPixmap()->draw_polygon(owner_.getGC(), true, points);
+       return *this;
+}
+
+
+Painter & GPainter::arc(int x, int y,
+       unsigned int w, unsigned int h,
+       int a1, int a2, LColor::color col)
+{
+       setForeground(owner_.getGC(), col);
+       owner_.getPixmap()->draw_arc(owner_.getGC(),
+                                    false, x, y, w, h, a1, a2);
+       return *this;
+}
+
+
+Painter & GPainter::image(int x, int y,
+       int w, int h,
+       lyx::graphics::Image const & i)
+{
+       lyx::graphics::xformsImage const & image =
+               static_cast<lyx::graphics::xformsImage const &>(i);
+       Pixmap pixmap = GDK_PIXMAP_XID(owner_.getPixmap()->gobj());
+       GC gc = GDK_GC_XGC(owner_.getGC()->gobj());
+       XCopyArea(owner_.getDisplay(), image.getPixmap(), pixmap,
+                 gc, 0, 0, w, h, x, y);
+       return *this;
+}
+
+
+Painter & GPainter::text(int x, int y,
+       string const & s, LyXFont const & f)
+{
+       size_t size = s.length() + 1;
+       wchar_t * wcs = (wchar_t *) alloca(size * sizeof(wchar_t));     
+       size = mbstowcs(wcs, s.c_str(), size);  
+       return text(x, y, wcs, size, f);
+}
+
+
+Painter & GPainter::text(int x, int y,
+       char c, LyXFont const & f)
+{
+       char s[2] = { c, '\0' };
+       return text(x, y, s, 1, f);
+}
+
+
+inline XftFont * getXftFont(LyXFont const & f)
+{
+       return fontLoader.load(f.family(), f.series(),
+                              f.realShape(), f.size());
+}
+
+
+namespace font_metrics
+{
+
+int width(wchar_t const *s, size_t n, LyXFont const & f);
+
+}
+
+
+Painter & GPainter::text(int x, int y, wchar_t const * s, int ls,
+                      LyXFont const & f)
+{
+       XftFont * font = getXftFont(f);
+       XftColor * xftClr = owner_.getColorHandler().
+               getXftColor(f.realColor());
+//     getXftColor(f.realColor());
+       XftDraw * draw = owner_.getXftDraw();
+       if (f.realShape() != LyXFont::SMALLCAPS_SHAPE) {
+               XftDrawString32(draw, xftClr, font, x, y,
+                               wcsToFcChar32StrFast(s), ls);
+       } else {
+               LyXFont smallfont(f);
+               smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
+               XftFont * fontS = getXftFont(smallfont);
+               wchar_t c;
+               int tmpx = x;
+               for(int i = 0; i < ls; ++i) {
+                       c = lyx::support::uppercase(s[i]);
+                       if(c != s[i]) {
+                               XftDrawString32(draw, xftClr, fontS, tmpx, y, 
+                                               wcsToFcChar32StrFast(&c), 1);
+                               tmpx += font_metrics::width(c, smallfont);
+                       } else {
+                               XftDrawString32(draw, xftClr, font, tmpx, y,
+                                               wcsToFcChar32StrFast(&c), 1);
+                               tmpx += font_metrics::width(c, f);
+                       }
+               }
+       }
+       if (f.underbar() == LyXFont::ON)
+               underline(f, x, y, font_metrics::width(s, ls, f));
+       return *this;
+}
+
+                                                               
+Painter & GPainter::text(int x, int y,
+       char const * s, size_t ls,
+       LyXFont const & f)
+{
+       boost::scoped_array<wchar_t> wcs(new wchar_t[ls + 1]);
+       size_t len;
+       if (fontLoader.isSpecial(f)) {
+               unsigned char const * us =
+                       reinterpret_cast<unsigned char const *>(s);
+               len = ls;
+               std::copy(us, us + ls, wcs.get());
+       } else
+               len = mbstowcs(wcs.get(), s, ls + 1);
+       return text(x, y, wcs.get(), len, f);
+}
diff --git a/src/frontends/gtk/GPainter.h b/src/frontends/gtk/GPainter.h
new file mode 100644 (file)
index 0000000..7f06c28
--- /dev/null
@@ -0,0 +1,129 @@
+// -*- C++ -*-
+/**
+ * \file GPainter.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GPAINTER_H
+#define GPAINTER_H
+
+#include <config.h>
+#include <X11/Xft/Xft.h>
+
+#include <map>
+#include "frontends/Painter.h"
+#include "LString.h"
+
+class LyXFont;
+class GWorkArea;
+
+/**
+ * GPainter - a painter implementation for Gtkmm
+ */
+class GPainter : public Painter {
+public:
+       GPainter(GWorkArea &);
+
+       /// return the width of the work area in pixels
+       virtual int paperWidth() const;
+       /// return the height of the work area in pixels
+       virtual int paperHeight() const;
+
+       void setForeground(Glib::RefPtr<Gdk::GC> gc, LColor::color clr);
+       void setLineParam(Glib::RefPtr<Gdk::GC> gc,
+                         line_style ls, line_width lw);
+       XftColor * getXftColor(LColor::color clr);
+       /// draw a line from point to point
+       virtual Painter & line(
+               int x1, int y1,
+               int x2, int y2,
+               LColor::color = LColor::foreground,
+               line_style = line_solid,
+               line_width = line_thin);
+
+       /**
+        * lines -  draw a set of lines
+        * @param xp array of points' x co-ords
+        * @param yp array of points' y co-ords
+        * @param np size of the points array
+        */
+       virtual Painter & lines(
+               int const * xp,
+               int const * yp,
+               int np,
+               LColor::color = LColor::foreground,
+               line_style = line_solid,
+               line_width = line_thin);
+
+       /// draw a rectangle
+       virtual Painter & rectangle(
+               int x, int y,
+               int w, int h,
+               LColor::color = LColor::foreground,
+               line_style = line_solid,
+               line_width = line_thin);
+
+       /// draw a filled rectangle
+       virtual Painter & fillRectangle(
+               int x, int y,
+               int w, int h,
+               LColor::color);
+
+       /// draw a filled (irregular) polygon
+       virtual Painter & fillPolygon(
+               int const * xp,
+               int const * yp,
+               int np,
+               LColor::color = LColor::foreground);
+
+       /// draw an arc
+       virtual Painter & arc(
+               int x, int y,
+               unsigned int w, unsigned int h,
+               int a1, int a2,
+               LColor::color = LColor::foreground);
+
+       /// draw a pixel
+       virtual Painter & point(
+               int x, int y,
+               LColor::color = LColor::foreground);
+
+       /// draw an image from the image cache
+       virtual Painter & image(int x, int y,
+               int w, int h,
+               lyx::graphics::Image const & image);
+
+       /// draw a string at position x, y (y is the baseline)
+       virtual Painter & text(int x, int y,
+               string const & str, LyXFont const & f);
+
+       /** Draw a string at position x, y (y is the baseline)
+        *  This is just for fast drawing
+        */
+       virtual Painter & text(int x, int y,
+               char const * str, size_t l,
+               LyXFont const & f);
+
+        virtual Painter & text(int x, int y, wchar_t const * str, int l,
+                              LyXFont const & f);
+
+       /// draw a char at position x, y (y is the baseline)
+       virtual Painter & text(int x, int y,
+                              char c, LyXFont const & f);
+
+       /// draw a wide string at position x, y
+       Painter & text(int x, int y,
+               XChar2b const * str, size_t l,
+               LyXFont const & f);
+
+private:
+       /// our owner who we paint upon
+       GWorkArea & owner_;
+};
+
+#endif // XPAINTER_H
diff --git a/src/frontends/gtk/GPrint.C b/src/frontends/gtk/GPrint.C
new file mode 100644 (file)
index 0000000..ba5e3bb
--- /dev/null
@@ -0,0 +1,156 @@
+// GPrint.C
+
+#include <config.h>
+#include <gtkmm.h>
+#include <libglademm.h>
+
+#include "GPrint.h"
+#include "ControlPrint.h"
+#include "support/filetools.h"
+#include "PrinterParams.h"
+#include "support/lstrings.h"
+
+
+GPrint::GPrint(Dialog & parent, string title)
+       : GViewCB<ControlPrint, GViewGladeB>(parent, title, false)
+{
+}
+
+
+void GPrint::apply()
+{
+       PrinterParams pp;
+       pp.target = printer_->get_active() ? PrinterParams::PRINTER : PrinterParams::FILE;
+       pp.printer_name = printerEntry_->get_text();
+       pp.file_name = printerEntry_->get_text();
+       pp.all_pages = all_->get_active();
+       pp.from_page = pp.to_page = 0;
+       if (!fromEntry_->get_text().empty()) {
+               pp.from_page = strToInt(fromEntry_->get_text());
+               if (!toEntry_->get_text().empty())
+                       pp.to_page = strToInt(toEntry_->get_text());
+       }
+       pp.odd_pages = odd_->get_active();
+       pp.even_pages = even_->get_active();
+       pp.count_copies = number_->get_value_as_int();
+       pp.sorted_copies = sorted_->get_active();
+       pp.reverse_order = reverse_->get_active();
+       controller().params() = pp;
+}
+
+
+void GPrint::update()
+{
+       PrinterParams & pp = controller().params();
+       printer_->set_active(pp.target == PrinterParams::PRINTER);
+       printerEntry_->set_text(pp.printer_name);
+       fileEntry_->set_text(pp.file_name);
+       all_->set_active(pp.all_pages);
+
+       string const from = ( pp.from_page ? tostr(pp.from_page) : string() );
+       string const to   = ( pp.to_page   ? tostr(pp.to_page)   : string() );
+       fromEntry_->set_text(from);
+       toEntry_->set_text(to);
+       odd_->set_active(pp.odd_pages);
+       even_->set_active(pp.even_pages);
+       reverse_->set_active(pp.reverse_order);
+       sorted_->set_active(pp.sorted_copies);
+       number_->set_value(pp.count_copies);
+       bool const enable_counter = pp.target == PrinterParams::PRINTER;
+       number_->set_sensitive(enable_counter);
+       sorted_->set_sensitive(enable_counter && pp.count_copies > 1);
+}
+
+
+void GPrint::updateUI()
+{
+       ButtonPolicy::SMInput activate = ButtonPolicy::SMI_VALID;
+       // disable OK/Apply buttons when file output is selected, but no file name entered
+       if (file_->get_active() && fileEntry_->get_text().empty())
+               activate = ButtonPolicy::SMI_INVALID;
+       // check 'from' and 'to' fields only when 'from/to' radio button is selected
+       if (fromTo_->get_active()) {
+               string from = fromEntry_->get_text();
+               string to = toEntry_->get_text();
+               if (from.empty() || (!to.empty() && strToInt(from) > strToInt(to)))
+                       activate = ButtonPolicy::SMI_INVALID;
+       }
+       bool const enableCounter = printer_->get_active();
+       number_->set_sensitive(enableCounter);
+       bool const enableSorted = enableCounter && number_->get_value_as_int() > 1;
+       sorted_->set_sensitive(enableSorted);
+       bc().input(activate);
+}
+
+
+void GPrint::onBrowse()
+{
+       string const inName = fileEntry_->get_text();
+       string const outName = Glib::locale_to_utf8(controller().Browse(Glib::locale_from_utf8(inName)));
+       if (outName != inName && !outName.empty())
+               fileEntry_->set_text(outName);
+       if (!outName.empty())
+               file_->set_active(true);
+       updateUI();
+}
+
+
+void GPrint::onTargetEdit(Gtk::Entry const * who)
+{
+       if (who == fileEntry_)
+               file_->set_active(true);
+       else if (who == printerEntry_)
+               printer_->set_active(true);
+       updateUI();
+}
+
+
+void GPrint::onFromToEdit()
+{
+       fromTo_->set_active(true);
+       updateUI();
+}
+
+
+void GPrint::doBuild()
+{
+       string const gladeName = LibFileSearch("glade", "print", "glade");
+       xml_ = Gnome::Glade::Xml::create(gladeName);
+       xml_->get_widget("Printer", printer_);
+       xml_->get_widget("File", file_);
+       xml_->get_widget("All", all_);
+       xml_->get_widget("FromTo", fromTo_);
+       xml_->get_widget("Odd", odd_);
+       xml_->get_widget("Even", even_);
+       xml_->get_widget("Reverse", reverse_);
+       xml_->get_widget("Number", number_);
+       xml_->get_widget("Sorted", sorted_);
+       xml_->get_widget("FromEntry", fromEntry_);
+       xml_->get_widget("ToEntry", toEntry_);
+       xml_->get_widget("PrinterEntry", printerEntry_);
+       xml_->get_widget("FileEntry", fileEntry_);
+       Gtk::Button * ok;
+       Gtk::Button * cancel;
+       Gtk::Button * apply;
+       xml_->get_widget("OkButton", ok);
+       xml_->get_widget("CancelButton", cancel);
+       xml_->get_widget("ApplyButton", apply);
+       bc().setOK(ok);
+       bc().setApply(apply);
+       bc().setCancel(cancel);
+       ok->signal_clicked().connect(SigC::slot(*this, &GViewBase::onOK));
+       apply->signal_clicked().connect(SigC::slot(*this, &GViewBase::onApply));
+       cancel->signal_clicked().connect(SigC::slot(*this, &GViewBase::onCancel));
+       Gtk::Button * browse;
+       xml_->get_widget("Browse", browse);
+       browse->signal_clicked().connect(SigC::slot(*this, &GPrint::onBrowse));
+       fileEntry_->signal_changed().connect(SigC::bind(SigC::slot(*this, &GPrint::onTargetEdit), fileEntry_));
+       printerEntry_->signal_changed().connect(SigC::bind(SigC::slot(*this, &GPrint::onTargetEdit), printerEntry_));
+       fromEntry_->signal_changed().connect(SigC::slot(*this, &GPrint::onFromToEdit));
+       toEntry_->signal_changed().connect(SigC::slot(*this, &GPrint::onFromToEdit));
+       printer_->signal_toggled().connect(SigC::slot(*this, &GPrint::updateUI));
+       file_->signal_toggled().connect(SigC::slot(*this, &GPrint::updateUI));
+       all_->signal_toggled().connect(SigC::slot(*this, &GPrint::updateUI));
+       fromTo_->signal_toggled().connect(SigC::slot(*this, &GPrint::updateUI));
+       number_->signal_changed().connect(SigC::slot(*this, &GPrint::updateUI));
+}
diff --git a/src/frontends/gtk/GPrint.h b/src/frontends/gtk/GPrint.h
new file mode 100644 (file)
index 0000000..a296335
--- /dev/null
@@ -0,0 +1,43 @@
+// -*- C++ -*-
+/*
+ * /file GPrint.h
+ */
+
+#ifndef GPRINT_H
+#define GPRINT_H
+
+#include "LString.h"
+#include "GViewBase.h"
+
+class ControlPrint;
+
+class GPrint : public GViewCB<ControlPrint, GViewGladeB>
+{
+public:
+       GPrint(Dialog & parent, string title = "Print Document");
+private:
+       virtual void apply();
+       virtual void update();
+       virtual void doBuild();
+       void updateUI();
+       void onBrowse();
+       void onTargetEdit(Gtk::Entry const * who);
+       void onFromToEdit();
+
+       Gtk::RadioButton * printer_;
+       Gtk::RadioButton * file_;
+       Gtk::RadioButton * all_;
+       Gtk::RadioButton * fromTo_;
+       Gtk::CheckButton * odd_;
+       Gtk::CheckButton * even_;
+       Gtk::CheckButton * reverse_;
+       Gtk::SpinButton * number_;
+       Gtk::CheckButton * sorted_;
+       Gtk::Entry * printerEntry_;
+       Gtk::Entry * fileEntry_;
+       Gtk::Entry * fromEntry_;
+       Gtk::Entry * toEntry_;
+};
+
+#endif
+
diff --git a/src/frontends/gtk/GScreen.C b/src/frontends/gtk/GScreen.C
new file mode 100644 (file)
index 0000000..3d4c6fe
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+ * \file GScreen.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include <algorithm>
+
+#include "frontends/screen.h"
+#include "frontends/font_metrics.h"
+#include "GWorkArea.h"
+#include "GScreen.h"
+#include "lyxtext.h"
+#include "lyxrow.h"
+#include "Painter.h"
+#include "WorkArea.h"
+#include "buffer.h"
+#include "BufferView.h"
+#include "insets/insettext.h"
+#include "language.h"
+#include "debug.h"
+
+
+GScreen::GScreen(GWorkArea & o)
+       : LyXScreen(), owner_(o)
+{
+       // the cursor isnt yet visible
+       cursorX_ = 0;
+       cursorY_ = 0;
+       cursorW_ = 0;
+       cursorH_ = 0;
+}
+
+
+GScreen::~GScreen()
+{
+}
+
+
+void GScreen::setCursorColor(Glib::RefPtr<Gdk::GC> gc)
+{
+       Gdk::Color * clr = owner_.getColorHandler().
+               getGdkColor(LColor::cursor);
+       gc->set_foreground(*clr);
+}
+
+
+void GScreen::showCursor(int x, int y,
+                        int h, Cursor_Shape shape)
+{
+       // Update the cursor color.
+       setCursorColor(owner_.getGC());
+
+       cursorX_ = x;
+       cursorY_ = y;
+       cursorH_ = h;
+
+       switch (shape) {
+       case BAR_SHAPE:
+               cursorW_ = 1;
+               break;
+       case L_SHAPE:
+               cursorW_ = cursorH_ / 3;
+               break;
+       case REVERSED_L_SHAPE:
+               cursorW_ = cursorH_ / 3;
+               cursorX_ = x - cursorW_ + 1;
+               break;
+       }
+
+       int fx, fy, fwidth, fheight, fdepth;
+       owner_.getWindow()->get_geometry(fx, fy, fwidth, fheight, fdepth);
+       cursorPixmap_ = Gdk::Pixmap::create(owner_.getWindow(),
+                                           cursorW_,
+                                           cursorH_,
+                                           fdepth);
+       cursorPixmap_->draw_drawable(owner_.getGC(),
+                                    owner_.getWindow(),
+                                    owner_.xpos() + cursorX_,
+                                    owner_.ypos() + cursorY_,
+                                    0, 0,
+                                    cursorW_,
+                                    cursorH_);
+       owner_.getWindow()->draw_line(owner_.getGC(),
+                                     x + owner_.xpos(),
+                                     y + owner_.ypos(),
+                                     x + owner_.xpos(),
+                                     y + h - 1 + owner_.ypos());
+       switch (shape) {
+       case BAR_SHAPE:
+               break;
+       case L_SHAPE:
+       case REVERSED_L_SHAPE:
+               owner_.getWindow()->draw_line(owner_.getGC(),
+                                             owner_.xpos() + cursorX_,
+                                             owner_.ypos() + y + h - 1,
+                                             owner_.xpos() + cursorX_ + cursorW_ - 1,
+                                             owner_.xpos() + y + h - 1);
+               break;
+       }
+}
+
+
+void GScreen::removeCursor()
+{
+       if (cursorPixmap_) {
+               owner_.getWindow()->draw_drawable(owner_.getGC(),
+                                                 cursorPixmap_,
+                                                 0, 0,
+                                                 cursorX_ + owner_.xpos(),
+                                                 cursorY_ + owner_.ypos(),
+                                                 cursorW_, cursorH_);
+       }
+}
+
+
+void GScreen::expose(int x, int y, int w, int h)
+{
+       lyxerr[Debug::GUI] << "expose " << w << 'x' << h
+               << '+' << x << '+' << y << std::endl;
+       owner_.getWindow()->draw_drawable(owner_.getGC(),
+                                         owner_.getPixmap(),
+                                         x, y,
+                                         x + owner_.xpos(),
+                                         y + owner_.ypos(),
+                                         w, h);
+}
diff --git a/src/frontends/gtk/GScreen.h b/src/frontends/gtk/GScreen.h
new file mode 100644 (file)
index 0000000..50587c6
--- /dev/null
@@ -0,0 +1,63 @@
+// -*- C++ -*-
+/**
+ * \file GScreen.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GSCREEN_H
+#define GSCREEN_H
+
+#include "screen.h"
+
+class GWorkArea;
+
+/** The class GScreen is used for the main Textbody.
+    Concretely, the screen is held in a pixmap.  This pixmap is kept up to
+    date and used to optimize drawing on the screen.
+    This class also handles the drawing of the cursor and partly the selection.
+ */
+class GScreen : public LyXScreen {
+public:
+       ///
+       GScreen(GWorkArea &);
+
+       ///
+       virtual ~GScreen();
+
+       /// Sets the cursor color to LColor::cursor.
+       virtual void setCursorColor(Glib::RefPtr<Gdk::GC> gc);
+       ///
+       virtual void removeCursor();
+       ///
+       virtual void showCursor(int x, int y, int h,
+                               Cursor_Shape shape);
+
+protected:
+       /// get the work area
+       virtual WorkArea & workarea() const { return owner_; }
+
+       /// Copies specified area of pixmap to screen
+       virtual void expose(int x, int y, int w, int h);
+
+private:
+       /// our owning widget
+       GWorkArea & owner_;
+
+       ///
+       Glib::RefPtr<Gdk::Pixmap> cursorPixmap_;
+       ///
+       int cursorX_;
+       ///
+       int cursorY_;
+       ///
+       int cursorW_;
+       ///
+       int cursorH_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GText.C b/src/frontends/gtk/GText.C
new file mode 100644 (file)
index 0000000..71c0141
--- /dev/null
@@ -0,0 +1,77 @@
+/**
+ * \file GText.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+#include <libglademm.h>
+
+#include "support/lstrings.h"
+#include "support/filetools.h"
+#include "ControlCommand.h"
+#include "GText.h"
+#include "IdSc.h"
+
+GText::GText(Dialog & parent, string const & title, string const & label)
+       : GViewCB<ControlCommand, GViewGladeB>(parent, title),
+         label_(label), entry_(0)
+{
+}
+
+void GText::apply()
+{
+       string const contents = Glib::locale_from_utf8(entry_->get_text());
+       controller().params().setContents(contents);
+}
+
+void GText::update()
+{
+       string const contents = lyx::support::trim(
+               controller().params().getContents());
+       entry_->set_text(Glib::locale_to_utf8(contents));
+}
+
+void GText::doBuild()
+{
+       string const gladeName =
+               lyx::support::LibFileSearch("glade", "text", "glade");
+       xml_ = Gnome::Glade::Xml::create(gladeName);
+       Gtk::Label * label;
+       Gtk::Button * restore;
+       Gtk::Button * cancel;
+       Gtk::Button * apply;
+       Gtk::Button * ok;
+       xml_->get_widget("Label", label);
+       xml_->get_widget("Text", entry_);
+       xml_->get_widget("Restore", restore);
+       xml_->get_widget("Cancel", cancel);
+       xml_->get_widget("Apply", apply);
+       xml_->get_widget("OK", ok);
+       label->set_text(Glib::locale_to_utf8(id_sc::id(label_)));
+       bcview().setOK(ok);
+       bcview().setApply(apply);
+       bcview().setCancel(cancel);
+       bcview().setRestore(restore);
+       bcview().addReadOnly(entry_);
+       ok->signal_clicked().connect(
+               SigC::slot(*this, &GViewBase::onOK));
+       apply->signal_clicked().connect(
+               SigC::slot(*this, &GViewBase::onApply));
+       cancel->signal_clicked().connect(
+               SigC::slot(*this, &GViewBase::onCancel));
+       restore->signal_clicked().connect(
+               SigC::slot(*this, &GViewBase::onRestore));
+       entry_->signal_changed().connect(
+               SigC::slot(*this, &GText::onEntryChanged));
+}
+
+void GText::onEntryChanged()
+{
+       bc().valid(!entry_->get_text().empty());
+}
diff --git a/src/frontends/gtk/GText.h b/src/frontends/gtk/GText.h
new file mode 100644 (file)
index 0000000..cb48034
--- /dev/null
@@ -0,0 +1,33 @@
+// -*- C++ -*-
+/**
+ * \file GText.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GTEXT_H
+#define GTEXT_H
+
+#include "GViewBase.h"
+#include "LString.h"
+
+class ControlCommand;
+
+class GText : public GViewCB<ControlCommand, GViewGladeB>
+{
+public:
+       GText(Dialog & parent, string const & title, string const & label);
+private:
+       virtual void apply();
+       virtual void update();
+       virtual void doBuild();
+       void onEntryChanged();
+       string const label_;
+       Gtk::Entry * entry_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GTimeout.C b/src/frontends/gtk/GTimeout.C
new file mode 100644 (file)
index 0000000..c4512f1
--- /dev/null
@@ -0,0 +1,69 @@
+/**
+ * \file gtk/GTimeout.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Baruch Even
+ * \author Michael Koziarski
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "GTimeout.h"
+#include "debug.h"
+
+
+Timeout::Timeout(unsigned int msec, Type t)
+       : pimpl_(new GTimeout(*this)), type(t), timeout_ms(msec)
+{}
+
+
+GTimeout::GTimeout(Timeout & owner)
+       : Timeout::Impl(owner)
+{
+}
+
+
+void GTimeout::reset()
+{
+       stop();
+}
+
+
+bool GTimeout::running() const
+{
+       return running_;
+}
+
+
+void GTimeout::start()
+{
+       if (conn_.connected()) {
+               lyxerr << "Timeout::start: already running!" << std::endl;
+               stop();
+       }
+
+       conn_ = Glib::signal_timeout().connect(
+                        SigC::slot(*this, &GTimeout::timeoutEvent),
+                        timeout_ms()
+                       );
+       running_ = true;
+}
+
+
+void GTimeout::stop()
+{
+       conn_.disconnect();
+       running_ = false;
+}
+
+
+bool GTimeout::timeoutEvent()
+{
+       emit();
+       return false; // discontinue emitting timeouts.
+}
diff --git a/src/frontends/gtk/GTimeout.h b/src/frontends/gtk/GTimeout.h
new file mode 100644 (file)
index 0000000..c2726a1
--- /dev/null
@@ -0,0 +1,47 @@
+// -*- C++ -*-
+/**
+ * \file gtk/GTimeout.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Baruch Even
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GTIMEOUT_H
+#define GTIMEOUT_H
+
+#include "frontends/Timeout.h"
+
+#include <sigc++/sigc++.h>
+
+/**
+ * This class executes the callback when the timeout expires
+ * using Gtk mechanisms
+ */
+class GTimeout : public Timeout::Impl, public SigC::Object {
+public:
+       ///
+       GTimeout(Timeout & owner_);
+       /// start the timer
+       void start();
+       /// stop the timer
+       void stop();
+       /// reset
+       void reset();
+       /// Is the timer running?
+       bool running() const;
+
+public:
+       /// The timeout signal, this gets called when the timeout passed.
+       bool timeoutEvent();
+private:
+       /// Timer connection
+       SigC::Connection conn_;
+       /// Used for running as SigC::Connection::connected() isn't const
+       bool running_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GToolbar.C b/src/frontends/gtk/GToolbar.C
new file mode 100644 (file)
index 0000000..80ea2f2
--- /dev/null
@@ -0,0 +1,261 @@
+/**
+ * \file GToolbar.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "GToolbar.h"
+#include "GView.h"
+#include "LyXAction.h"
+#include "lyxfunc.h"
+#include "FuncStatus.h"
+#include "buffer.h"
+#include "funcrequest.h"
+#include "gettext.h"
+#include "Tooltips.h"
+#include "support/filetools.h"
+#include "support/lstrings.h"
+#include "debug.h"
+
+
+namespace
+{
+
+
+char const * gToolData = "tool_data";
+
+
+inline void comboClear(Gtk::Combo & combo)
+{
+       std::vector<Glib::ustring> strings;
+       strings.push_back("");
+       combo.set_popdown_strings(strings);
+}
+
+
+inline bool comboIsEmpty(Gtk::Combo & combo)
+{
+       std::vector<Glib::ustring> strings = combo.get_popdown_strings();
+       return (strings.empty() || (strings.size() == 1 && strings[0] == ""));
+}
+
+
+}
+
+
+GToolbar::GToolbar(LyXView * lyxView, int /*x*/, int /*y*/)
+       : view_(lyxView), internal_(false)
+{
+       combo_.set_value_in_list();
+       combo_.get_entry()->set_editable(false);
+       combo_.unset_flags(Gtk::CAN_FOCUS | Gtk::CAN_DEFAULT);
+       combo_.get_entry()->unset_flags(Gtk::CAN_FOCUS | Gtk::CAN_DEFAULT);
+       comboClear(combo_);
+       combo_.get_entry()->signal_changed().connect(
+               SigC::slot(*this,
+                          &GToolbar::onLayoutSelected));
+       GView * gview = static_cast<GView*>(lyxView);
+       vbox_.show();
+       Gtk::VBox & vbox = gview->getVBox();
+       vbox.children().push_back(Gtk::Box_Helpers::Element(vbox_,
+                                                           Gtk::PACK_SHRINK));
+}
+
+
+GToolbar::~GToolbar()
+{
+}
+
+
+void GToolbar::add(ToolbarBackend::Toolbar const & tb)
+{
+       Gtk::Toolbar * toolbar = manage(new Gtk::Toolbar());
+       ToolbarBackend::item_iterator it = tb.items.begin();
+       ToolbarBackend::item_iterator end = tb.items.end();
+       for (; it != end; ++it)
+               add(toolbar, it->first, it->second);
+       toolbar->set_toolbar_style(Gtk::TOOLBAR_ICONS);
+       toolbar->show();
+       vbox_.children().push_back(
+               Gtk::Box_Helpers::Element(*toolbar,
+                                         Gtk::PACK_SHRINK));
+       toolbars_.push_back(toolbar);
+}
+
+
+void GToolbar::add(Gtk::Toolbar * toolbar, 
+                        int action,
+                        string const & tooltip)
+{
+       switch (action) {
+       case ToolbarBackend::SEPARATOR:
+               toolbar->tools().push_back(Gtk::Toolbar_Helpers::Space());
+               break;
+       case ToolbarBackend::MINIBUFFER:
+               // Not supported yet.
+               break;
+       case ToolbarBackend::LAYOUTS:
+       {
+               combo_.show();
+               toolbar->tools().push_back(
+                       Gtk::Toolbar_Helpers::Element(combo_));
+               toolbar->tools().back().get_widget()->set_data(
+                       gToolData,
+                       reinterpret_cast<void*>(LFUN_LAYOUT));
+               break;
+       }
+       default:
+       {
+               Glib::ustring xpmName = 
+                       Glib::locale_to_utf8(toolbarbackend.getIcon(action));
+               Glib::ustring tip = Glib::locale_to_utf8(tooltip);
+               if (xpmName.size() == 0) {
+                       toolbar->tools().push_back(
+                               Gtk::Toolbar_Helpers::ButtonElem(
+                                       "",
+                                       SigC::bind(SigC::slot(*this, &GToolbar::onButtonClicked),
+                                                  action),
+                                       tip));
+               } else {
+                       Gtk::Image * image = 
+                               Gtk::manage(new Gtk::Image(xpmName));
+                       image->show();
+                       toolbar->tools().push_back(
+                               Gtk::Toolbar_Helpers::ButtonElem(
+                                       "",
+                                       *image,
+                                       SigC::bind(SigC::slot(*this, &GToolbar::onButtonClicked),
+                                                  action),
+                                       tip));
+               }
+               toolbar->tools().back().get_content()->set_data(
+                       gToolData,
+                       reinterpret_cast<void*>(action));
+               break;
+       }
+       }
+}
+
+
+void GToolbar::onButtonClicked(int action)
+{
+       view_->getLyXFunc().dispatch(action, true);
+}
+
+
+void GToolbar::onLayoutSelected()
+{
+       if (internal_)
+               return;
+       string layoutGuiName = combo_.get_entry()->get_text();
+       // we get two signal, one of it is empty and useless
+       if (layoutGuiName.empty())
+               return;
+       LyXTextClass const & tc =
+               view_->buffer()->params.getLyXTextClass();
+
+       LyXTextClass::const_iterator end = tc.end();
+       for (LyXTextClass::const_iterator cit = tc.begin();
+            cit != end; ++cit) {
+               if ((*cit)->name() == layoutGuiName) {
+                       view_->getLyXFunc().dispatch(
+                               FuncRequest(LFUN_LAYOUT, (*cit)->name()),
+                               true);
+                       return;
+               }
+       }
+       lyxerr << "ERROR (GToolbar::layoutSelected): layout not found! name : "
+              << layoutGuiName
+              << std::endl;
+}
+
+
+void GToolbar::displayToolbar(ToolbarBackend::Toolbar const & /*tb*/, bool /*show*/)
+{
+}
+
+
+void GToolbar::update()
+{
+       std::vector<Gtk::Toolbar*>::iterator itToolbar;
+       for (itToolbar = toolbars_.begin();
+            itToolbar != toolbars_.end(); ++itToolbar) {
+               Gtk::Toolbar * toolbar = *itToolbar;
+               Gtk::Toolbar_Helpers::ToolList::iterator it;
+               for (it = toolbar->tools().begin();
+                    it != toolbar->tools().end(); ++it) {
+                       Gtk::Widget * widget;
+                       switch (it->get_type()) {
+                       case Gtk::TOOLBAR_CHILD_WIDGET:
+                               widget = it->get_widget();
+                               break;
+                       case Gtk::TOOLBAR_CHILD_SPACE:
+                               continue;
+                       default:
+                               widget = it->get_content();
+                       }
+                       int action = reinterpret_cast<int>(
+                               widget->get_data(gToolData));
+                       FuncStatus const status = view_->
+                               getLyXFunc().getStatus(action);
+                       bool sensitive = !status.disabled();
+                       widget->set_sensitive(sensitive);
+                       if (it->get_type() != Gtk::TOOLBAR_CHILD_BUTTON)
+                               return;
+                       if (status.onoff(true))
+                               static_cast<Gtk::Button*>(widget)->
+                                       set_relief(Gtk::RELIEF_NORMAL);
+                       if (status.onoff(false))
+                               static_cast<Gtk::Button*>(widget)->
+                                       set_relief(Gtk::RELIEF_NONE);
+               }
+       }
+}
+
+
+void GToolbar::setLayout(string const & layout)
+{
+       LyXTextClass const & tc =
+               view_->buffer()->params.getLyXTextClass();
+       internal_ = true;
+       combo_.get_entry()->set_text(tc[layout]->name());
+       internal_ = false;
+}
+
+
+void GToolbar::updateLayoutList()
+{
+       LyXTextClass const & tc =
+               view_->buffer()->params.getLyXTextClass();
+       LyXTextClass::const_iterator end = tc.end();
+       std::vector<Glib::ustring> strings;
+       for (LyXTextClass::const_iterator cit = tc.begin();
+            cit != end; ++cit)
+               if ((*cit)->obsoleted_by().empty())
+                       strings.push_back(
+                               Glib::locale_to_utf8((*cit)->name()));
+       internal_ = true;
+       combo_.set_popdown_strings(strings);
+       internal_ = false;
+}
+
+
+void GToolbar::openLayoutList()
+{
+       combo_.get_list()->activate();
+}
+
+
+void GToolbar::clearLayoutList()
+{
+       internal_ = true;
+       comboClear(combo_);
+       internal_ = false;
+}
diff --git a/src/frontends/gtk/GToolbar.h b/src/frontends/gtk/GToolbar.h
new file mode 100644 (file)
index 0000000..6779fd3
--- /dev/null
@@ -0,0 +1,62 @@
+// -*- C++ -*-
+/**
+ * \file GToolbar.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef TOOLBAR_PIMPL_H
+#define TOOLBAR_PIMPL_H
+
+#include <gtkmm.h>
+#include "frontends/Toolbar.h"
+#include "ToolbarBackend.h"
+#include "LString.h"
+
+class GToolbar : public Toolbar, public SigC::Object
+{
+public:
+       GToolbar(LyXView * o, int x, int y);
+
+       ~GToolbar();
+
+       // add a new toolbar
+       void add(ToolbarBackend::Toolbar const & tb);
+
+       /// add a new button to the toolbar.
+       void add(Gtk::Toolbar * toolbar,
+                int action,
+                string const & tooltip);
+
+       /// display toolbar, not implemented
+       void displayToolbar(ToolbarBackend::Toolbar const & tb, bool show);
+
+       /// update the state of the icons
+       void update();
+
+       /// select the right layout in the combox
+       void setLayout(string const & layout);
+
+       /// Populate the layout combox; re-do everything if force is true.
+       void updateLayoutList();
+
+       /// Drop down the layout list
+       void openLayoutList();
+
+       /// Erase the layout list
+       void clearLayoutList();
+private:
+       void onButtonClicked(int action);
+       void onLayoutSelected();
+       Gtk::VBox vbox_;
+       std::vector<Gtk::Toolbar*> toolbars_;
+       Gtk::Combo combo_;
+       LyXView * view_;
+       bool internal_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GView.C b/src/frontends/gtk/GView.C
new file mode 100644 (file)
index 0000000..75181b4
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * \file GView.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "GView.h"
+#include "MenuBackend.h"
+#include "support/filetools.h"
+#include "GMenubar.h"
+#include "GToolbar.h"
+#include "BufferView.h"
+#include "XWorkArea.h"
+#include "lyx_cb.h"
+#include "GMiniBuffer.h"
+#include "lyxfunc.h"
+#include <boost/bind.hpp>
+
+BufferView * current_view;
+
+GView * GView::view_ = 0;
+
+
+GView::GView()
+{
+       view_ = this;
+       vbox_.reset(new Gtk::VBox());
+       add(*vbox_.get());
+       menubar_.reset(new GMenubar(this, menubackend));
+       toolbar_.reset(new GToolbar(this, 0, 0));
+       toolbar_->init();
+       bufferview_.reset(new BufferView(this, 0, 0, 300, 300));
+       ::current_view = bufferview_.get();
+       minibuffer_.reset(new GMiniBuffer(this, *controlcommand_));
+       vbox_->show();
+       focus_command_buffer.connect(
+               boost::bind(&GMiniBuffer::editMode, minibuffer_.get()));
+       view_state_changed.connect(boost::bind(&GView::showViewState, this));
+       signal_focus_in_event().connect(SigC::slot(*this, &GView::onFocusIn));
+       set_default_size(500, 550);
+       // Make sure the buttons are disabled if needed.
+       updateToolbar();
+       string const iconName = 
+               lyx::support::LibFileSearch("images", "lyx", "xpm");
+       if (!iconName.empty())
+               set_icon_from_file(iconName);
+}
+
+
+GView::~GView()
+{
+}
+
+
+bool GView::on_delete_event(GdkEventAny * /*event*/)
+{
+       QuitLyX();
+       return true;
+}
+
+
+bool GView::onFocusIn(GdkEventFocus * /*event*/)
+{
+       workArea_->grab_focus();
+       return true;
+}
+
+
+void GView::prohibitInput() const
+{
+       view()->hideCursor();
+       const_cast<GView*>(this)->set_sensitive(false);
+}
+
+
+void GView::allowInput() const
+{
+       const_cast<GView*>(this)->set_sensitive(true);
+}
+
+
+void GView::message(string const & msg)
+{
+       minibuffer_->message(msg);
+}
+
+
+void GView::showViewState()
+{
+       message(getLyXFunc().view_status_message());
+}
+
+
+void GView::setWindowTitle(string const & t, string const & /*it*/)
+{
+       set_title(Glib::locale_to_utf8(t));
+}
+
+
+void GView::busy(bool yes) const
+{
+       if (yes ) {
+               view()->hideCursor();
+               Gdk::Cursor cursor(Gdk::WATCH);
+               const_cast<GView*>(this)->get_window()->set_cursor(cursor);
+               const_cast<GView*>(this)->set_sensitive(false);
+       } else {
+               const_cast<GView*>(this)->get_window()->set_cursor();
+               const_cast<GView*>(this)->set_sensitive(true);
+       }
+}
+
+
+void GView::clearMessage()
+{
+       message(getLyXFunc().view_status_message());
+}
diff --git a/src/frontends/gtk/GView.h b/src/frontends/gtk/GView.h
new file mode 100644 (file)
index 0000000..cf1d312
--- /dev/null
@@ -0,0 +1,48 @@
+// -*- C++ -*-
+/**
+ * \file GView.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GVIEW_H
+#define GVIEW_H
+
+#include "frontends/LyXView.h"
+#include "bufferview_funcs.h"
+#include <memory>
+class GMiniBuffer;
+
+class GView : public LyXView, public Gtk::Window
+{
+public:
+       virtual ~GView();
+
+       virtual void prohibitInput() const;
+       virtual void allowInput() const;
+       virtual void message(string const &);
+       Gtk::VBox & getVBox() { return *vbox_.get(); }
+       GView();
+       bool on_delete_event(GdkEventAny * event);
+       void focusWorkArea() { workArea_->grab_focus(); }
+       void setGWorkArea(Gtk::Widget * w) { workArea_ = w; }
+       static GView * instance() { return view_; }
+       /// show busy cursor
+       virtual void busy(bool) const;
+       /// clear any temporary message and replace with current status
+       virtual void clearMessage();
+private:
+       void showViewState();
+       bool onFocusIn(GdkEventFocus * event);
+       virtual void setWindowTitle(string const & t, string const & it);
+       static GView * view_;
+       std::auto_ptr<Gtk::VBox> vbox_;
+       boost::scoped_ptr<GMiniBuffer> minibuffer_;
+       Gtk::Widget * workArea_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GViewBase.C b/src/frontends/gtk/GViewBase.C
new file mode 100644 (file)
index 0000000..07d8d6c
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * \file GViewBase.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "GViewBase.h"
+#include "ControlButtons.h"
+#include "support/filetools.h"
+
+
+GViewBase::GViewBase(Dialog & parent, string const & t, bool allowResize) :
+       Dialog::View(parent, t), allowResize_(allowResize)
+{
+}
+
+
+GViewBase::~GViewBase()
+{
+}
+
+
+void GViewBase::hide()
+{
+       window()->hide();
+}
+
+
+void GViewBase::build()
+{
+       doBuild();
+       string const iconName =
+               lyx::support::LibFileSearch("images", "lyx", "xpm");
+       if (!iconName.empty())
+               window()->set_icon_from_file(iconName);
+       window()->signal_delete_event().connect(
+               SigC::slot(*this, &GViewBase::onDeleteEvent));
+       window()->set_title(Glib::locale_to_utf8(getTitle()));
+}
+
+
+void GViewBase::show()
+{
+       if (!window()) {
+               build();
+       }
+       window()->show();
+}
+
+
+bool GViewBase::isVisible() const
+{
+       return window() && window()->is_visible();
+}
+
+
+GBC & GViewBase::bcview()
+{
+       return static_cast<GBC &>(dialog().bc().view());
+}
+
+
+void GViewBase::onApply()
+{
+       dialog().ApplyButton();
+}
+
+
+void GViewBase::onOK()
+{
+       dialog().OKButton();
+}
+
+
+void GViewBase::onCancel()
+{
+       dialog().CancelButton();
+}
+
+
+void GViewBase::onRestore()
+{
+       dialog().RestoreButton();
+}
+
+
+bool GViewBase::onDeleteEvent(GdkEventAny *)
+{
+       dialog().CancelButton();
+       return false;
+}
+
+
+GViewGladeB::GViewGladeB(Dialog & parent, string const & t, bool allowResize) :
+       GViewBase(parent, t, allowResize)
+{
+}
+
+
+Gtk::Window * GViewGladeB::window()
+{
+       Gtk::Window * win;
+       if (!xml_)
+               return 0;
+       xml_->get_widget("dialog", win);
+       return win;
+}
+
+
+const Gtk::Window * GViewGladeB::window() const
+{
+       Gtk::Window * win;
+       if (!xml_)
+               return 0;
+       xml_->get_widget("dialog", win);
+       return win;
+}
diff --git a/src/frontends/gtk/GViewBase.h b/src/frontends/gtk/GViewBase.h
new file mode 100644 (file)
index 0000000..0b9d88a
--- /dev/null
@@ -0,0 +1,123 @@
+// -*- C++ -*-
+/**
+ * \file GViewBase.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GVIEWBASE_H
+#define GVIEWBASE_H
+
+#include <gtkmm.h>
+#include <libglademm.h>
+#include <boost/scoped_ptr.hpp>
+#include "Dialog.h"
+#include "ButtonPolicies.h"
+#include "GBC.h"
+
+class GViewBase : public Dialog::View, public SigC::Object
+{
+public:
+       GViewBase(Dialog &, string const &, bool allowResize);
+       virtual ~GViewBase();
+protected:
+       // Build the dialog
+       virtual void build();
+       virtual void doBuild() = 0;
+       // Hide the dialog
+       virtual void hide();
+       // Create the dialog if necessary, update it and display it.
+       virtual void show();
+       //
+       virtual bool isVisible() const;
+       GBC & bcview();
+       void onApply();
+       void onOK();
+       void onCancel();
+       void onRestore();
+       bool onDeleteEvent(GdkEventAny *);
+private:
+       virtual Gtk::Window * window() = 0;
+       virtual Gtk::Window const * window() const = 0;
+       bool allowResize_;
+};
+
+template <class Dialog>
+class GViewDB : public GViewBase
+{
+protected:
+       GViewDB(Dialog &, string const &, bool allowResize);
+       virtual const Gtk::Window * window() const;
+       virtual Gtk::Window * window();
+       boost::scoped_ptr<Dialog> dialog_;
+};
+
+
+template <class Dialog>
+GViewDB<Dialog>::GViewDB(Dialog & parent, string const & t, bool allowResize) :
+       GViewBase(parent, t, allowResize)
+{
+}
+
+
+template <class Dialog>
+Gtk::Window * GViewDB<Dialog>::window()
+{
+       return dialog_.get();
+}
+
+
+template <class Dialog>
+const Gtk::Window * GViewDB<Dialog>::window() const
+{
+       return dialog_.get();
+}
+
+
+class GViewGladeB : public GViewBase
+{
+protected:
+       GViewGladeB(Dialog & parent, string const & t, bool allowResize);
+       virtual const Gtk::Window * window() const;
+       virtual Gtk::Window * window();
+       Glib::RefPtr<Gnome::Glade::Xml> xml_;
+};
+
+
+template <class Controller, class Base>
+class GViewCB : public Base
+{
+public:
+       Controller & controller();
+       Controller const & controller() const;
+protected:
+       GViewCB(Dialog & parent, string const & t, bool allowResize = false);
+};
+
+
+template <class Controller, class Base>
+GViewCB<Controller, Base>::GViewCB(Dialog & parent, string const & t,
+                                  bool allowResize) :
+       Base(parent, t, allowResize)
+{
+}
+
+
+template <class Controller, class Base>
+Controller & GViewCB<Controller, Base>::controller()
+{
+       return static_cast<Controller &>(getController());
+}
+
+
+template <class Controller, class Base>
+Controller const & GViewCB<Controller, Base>::controller() const
+{
+       return static_cast<Controller const &>(getController());
+}
+
+#endif
diff --git a/src/frontends/gtk/GWorkArea.C b/src/frontends/gtk/GWorkArea.C
new file mode 100644 (file)
index 0000000..2ab906b
--- /dev/null
@@ -0,0 +1,355 @@
+/**
+ * \file GWorkArea.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+#include <X11/Xft/Xft.h>
+
+#include "GWorkArea.h"
+#include "debug.h"
+#include "funcrequest.h"
+#include "GView.h"
+#include "GtkmmX.h"
+#include "GLyXKeySym.h"
+
+ColorCache colorCache;
+
+
+void ColorCache::clear()
+{
+       MapIt it = cache_.begin();
+       for (; it != cache_.end(); ++it)
+               delete it->second;
+       cache_.clear();
+       MapIt2 it2 = cache2_.begin();
+       for (; it2 != cache2_.end(); ++it2)
+               delete it2->second;
+       cache2_.clear();
+}
+
+
+XftColor * ColorHandler::getXftColor(LColor::color clr)
+{
+       XftColor * xclr = colorCache.getXftColor(clr);
+       if (!xclr) {
+               xclr = new XftColor;
+               Colormap colormap = GDK_COLORMAP_XCOLORMAP(
+                       owner_.getColormap()->gobj());
+               Visual * visual = GDK_VISUAL_XVISUAL(
+                       owner_.getColormap()->get_visual()->gobj());
+               XftColorAllocName(owner_.getDisplay(), visual, colormap,
+                                 lcolor.getX11Name(clr).c_str(), xclr);
+               colorCache.cacheXftColor(clr, xclr);
+       }
+       return xclr;
+}
+
+
+Gdk::Color * ColorHandler::getGdkColor(LColor::color clr)
+{
+       Gdk::Color * gclr = colorCache.getColor(clr);
+       if (!gclr) {
+               gclr = new Gdk::Color;
+               gclr->parse(lcolor.getX11Name(clr));
+               owner_.getColormap()->alloc_color(*gclr);
+               colorCache.cacheColor(clr, gclr);
+       }
+       return gclr;
+}
+
+
+namespace
+{
+
+
+mouse_button::state gtkButtonState(unsigned int state)
+{
+       mouse_button::state b = mouse_button::none;
+       if (state & GDK_BUTTON1_MASK)
+               b = mouse_button::button1;
+       else if (state & GDK_BUTTON2_MASK)
+               b = mouse_button::button2;
+       else if (state & GDK_BUTTON3_MASK)
+               b = mouse_button::button3;
+       else if (state & GDK_BUTTON3_MASK)
+               b = mouse_button::button3;
+       else if (state & GDK_BUTTON4_MASK)
+               b = mouse_button::button4;
+       else if (state & GDK_BUTTON5_MASK)
+               b = mouse_button::button5;
+       return b;
+}
+
+
+key_modifier::state gtkKeyState(guint state)
+{
+       key_modifier::state k = key_modifier::none;
+       if (state & GDK_CONTROL_MASK)
+               k |= key_modifier::ctrl;
+       if (state & GDK_SHIFT_MASK)
+               k |= key_modifier::shift;
+       if (state & GDK_MOD1_MASK)
+               k |= key_modifier::alt;
+       return k;
+}
+
+
+void inputCommitRelay(GtkIMContext */*imcontext*/, gchar * str, GWorkArea * area)
+{
+       area->inputCommit(str);
+}
+
+
+}
+
+
+GWorkArea::GWorkArea(int width, int height)
+       : workAreaPixmap_(0), painter_(*this), draw_(0), colorHandler_(*this)
+{
+       workArea_.set_size_request(width, height);
+       workArea_.set_double_buffered(false);
+       workArea_.add_events(Gdk::STRUCTURE_MASK | Gdk::EXPOSURE_MASK |
+                            Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK |
+                            Gdk::KEY_PRESS_MASK | Gdk::BUTTON1_MOTION_MASK);
+       workArea_.signal_expose_event().connect(
+               SigC::slot(*this, &GWorkArea::onExpose));
+       workArea_.signal_configure_event().connect(
+               SigC::slot(*this, &GWorkArea::onConfigure));
+       workArea_.signal_button_press_event().connect(
+               SigC::slot(*this, &GWorkArea::onButtonPress));
+       workArea_.signal_button_release_event().connect(
+               SigC::slot(*this, &GWorkArea::onButtonRelease));
+       workArea_.signal_key_press_event().connect(
+               SigC::slot(*this, &GWorkArea::onKeyPress));
+       workArea_.signal_motion_notify_event().connect(
+               SigC::slot(*this, &GWorkArea::onMotionNotify));
+       workArea_.show();
+       vscrollbar_.get_adjustment()->signal_value_changed().connect(
+               SigC::slot(*this, &GWorkArea::onScroll));
+       vscrollbar_.show();
+       hbox_.children().push_back(Gtk::Box_Helpers::Element(workArea_));
+       hbox_.children().push_back(
+               Gtk::Box_Helpers::Element(vscrollbar_,Gtk::PACK_SHRINK));
+       hbox_.show();
+       GView::instance()->getVBox().children().push_back(
+               Gtk::Box_Helpers::Element(hbox_));
+       workArea_.set_flags(workArea_.get_flags() | Gtk::CAN_DEFAULT |
+                           Gtk::CAN_FOCUS);
+       workArea_.grab_default();
+       GView::instance()->setGWorkArea(&workArea_);
+       imContext_ = GTK_IM_CONTEXT(gtk_im_multicontext_new());
+       g_signal_connect(G_OBJECT(imContext_), "commit",
+                        G_CALLBACK(&inputCommitRelay),
+                        this);
+}
+
+
+GWorkArea::~GWorkArea()
+{
+       g_object_unref(imContext_);
+}
+
+
+bool GWorkArea::onExpose(GdkEventExpose * event)
+{
+       workArea_.get_window()->draw_drawable(
+               workArea_.get_style()->get_black_gc(),
+               workAreaPixmap_,
+               event->area.x, event->area.y,
+               event->area.x, event->area.y,
+               event->area.width, event->area.height);
+       return true;
+}
+
+
+bool GWorkArea::onConfigure(GdkEventConfigure * /*event*/)
+{
+       int x, y, width, height, depth;
+       workArea_.get_window()->get_geometry(x, y, width, height, depth);
+       if (draw_)
+               XftDrawDestroy(draw_);
+       workAreaPixmap_ = Gdk::Pixmap::create(workArea_.get_window(),
+                                             width, height, depth);
+       Pixmap pixmap = GDK_PIXMAP_XID(workAreaPixmap_->gobj());
+       Colormap colormap = GDK_COLORMAP_XCOLORMAP(
+               workArea_.get_colormap()->gobj());
+       Visual * visual = GDK_VISUAL_XVISUAL(
+               workArea_.get_colormap()->get_visual()->gobj());
+       draw_ = XftDrawCreate(getDisplay(), pixmap,
+                             visual, colormap);
+       if (!workAreaGC_) {
+               workAreaGC_ = Gdk::GC::create(workArea_.get_window());
+               Gdk::Cursor cursor(Gdk::XTERM);
+               workArea_.get_window()->set_cursor(cursor);
+               gtk_im_context_set_client_window(
+                       imContext_, workArea_.get_window()->gobj());
+       }
+       workAreaResize();
+       return true;
+}
+
+
+void GWorkArea::setScrollbarParams(int height, int pos, int line_height)
+{
+       Gtk::Adjustment * adjustment = vscrollbar_.get_adjustment();
+       adjustment->set_lower(0);
+       int workAreaHeight = workHeight();
+       if (!height || height < workAreaHeight) {
+               adjustment->set_upper(workAreaHeight);
+               adjustment->set_page_size(workAreaHeight);
+               adjustment->set_value(0);
+               adjustment->changed();
+               return;
+       }
+       adjustment->set_step_increment(line_height);
+       adjustment->set_page_increment(workAreaHeight - line_height);
+       adjustment->set_upper(height);
+       adjustment->set_page_size(workAreaHeight);
+       adjustment->set_value(pos);
+       adjustment->changed();
+}
+
+
+void GWorkArea::onScroll()
+{
+       double val = vscrollbar_.get_adjustment()->get_value();
+       scrollDocView(static_cast<int>(val));
+}
+
+
+bool GWorkArea::onButtonPress(GdkEventButton * event)
+{
+       kb_action ka = LFUN_MOUSE_PRESS;
+       switch (event->type) {
+       case GDK_BUTTON_PRESS:
+               ka = LFUN_MOUSE_PRESS;
+               break;
+       case GDK_2BUTTON_PRESS:
+               ka = LFUN_MOUSE_DOUBLE;
+               break;
+       case GDK_3BUTTON_PRESS:
+               ka = LFUN_MOUSE_TRIPLE;
+               break;
+       default:
+               break;
+       }
+       dispatch(FuncRequest(ka,
+                            static_cast<int>(event->x),
+                            static_cast<int>(event->y),
+                            static_cast<mouse_button::state>(event->button)));
+       workArea_.grab_focus();
+       return true;
+}
+
+
+bool GWorkArea::onButtonRelease(GdkEventButton * event)
+{
+       dispatch(FuncRequest(LFUN_MOUSE_RELEASE,
+                            static_cast<int>(event->x),
+                            static_cast<int>(event->y),
+                            static_cast<mouse_button::state>(event->button)));
+       return true;
+}
+
+
+bool GWorkArea::onMotionNotify(GdkEventMotion * event)
+{
+       static guint32 timeBefore;
+       Gtk::Adjustment * adjustment = vscrollbar_.get_adjustment();
+       double step = adjustment->get_step_increment();
+       double value = adjustment->get_value();
+       if (event->x < 0)
+               value -= step;
+       else if (event->x > workArea_.get_height())
+               value += step;
+       if (value != adjustment->get_value()) {
+               if (event->time - timeBefore > 200) {
+                       adjustment->set_value(value);
+                       adjustment->value_changed();
+               }
+               timeBefore = event->time;
+       }
+       dispatch(FuncRequest(LFUN_MOUSE_MOTION,
+                            static_cast<int>(event->x),
+                            static_cast<int>(event->y),
+                            gtkButtonState(event->state)));
+       return true;
+}
+
+
+void GWorkArea::inputCommit(gchar * str)
+{
+       inputCache_ = Glib::locale_from_utf8(str);
+}
+
+
+bool GWorkArea::onKeyPress(GdkEventKey * event)
+{
+#ifdef I18N
+       inputCache_ = "";
+       bool inputGet = gtk_im_context_filter_keypress(imContext_, event);
+       // cope with ascii
+       if ((inputGet && inputCache_.size() == 1 && inputCache_[0] < 128) ||
+           !inputGet) {
+#endif
+               GLyXKeySym *glk = new GLyXKeySym(event->keyval);
+               workAreaKeyPress(LyXKeySymPtr(glk),
+                                gtkKeyState(event->state));
+#ifdef I18N
+       } else if (!inputCache_.empty())
+               workAreaCJK_IMprocess(inputCache_.size(), inputCache_.data());
+#endif
+       return true;
+}
+
+
+void GWorkArea::onClipboardGet(Gtk::SelectionData & /*selection_data*/,
+                              guint /*info*/)
+{
+       selectionRequested();   
+}
+
+
+void GWorkArea::onClipboardClear()
+{
+//     selectionLost();
+}
+
+
+void GWorkArea::haveSelection(bool toHave) const
+{
+       if (toHave) {
+               Glib::RefPtr<Gtk::Clipboard> clipboard =
+                       Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
+               std::vector<Gtk::TargetEntry> listTargets;
+               listTargets.push_back(Gtk::TargetEntry("UTF8_STRING"));
+               clipboard->set(listTargets,
+                              SigC::slot(const_cast<GWorkArea&>(*this),
+                                         &GWorkArea::onClipboardGet),
+                              SigC::slot(const_cast<GWorkArea&>(*this),
+                                         &GWorkArea::onClipboardClear));
+       }
+}
+
+
+string const GWorkArea::getClipboard() const
+{
+       Glib::RefPtr<Gtk::Clipboard> clipboard =
+               Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
+       return Glib::locale_from_utf8(clipboard->wait_for_text());
+}
+
+
+void GWorkArea::putClipboard(string const & str) const
+{
+       Glib::RefPtr<Gtk::Clipboard> clipboard =
+               Gtk::Clipboard::get(GDK_SELECTION_PRIMARY);
+       clipboard->set_text(Glib::locale_to_utf8(str));
+}
diff --git a/src/frontends/gtk/GWorkArea.h b/src/frontends/gtk/GWorkArea.h
new file mode 100644 (file)
index 0000000..ae7940f
--- /dev/null
@@ -0,0 +1,125 @@
+// -*- C++ -*-
+/**
+ * \file GWorkArea.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GWORKAREA_H
+#define GWORKAREA_H
+
+#include <gdk/gdkx.h>
+#include "frontends/WorkArea.h"
+#include "GPainter.h"
+#include "LColor.h"
+#include <gtk/gtk.h>
+#include <X11/Xft/Xft.h>
+
+class ColorCache
+{
+       typedef std::map<LColor::color, Gdk::Color *> Map;
+       typedef Map::iterator MapIt;
+       typedef std::map<LColor::color, XftColor *> Map2;
+       typedef Map2::iterator MapIt2;
+public:
+       ~ColorCache() { clear(); }
+       Gdk::Color * getColor(LColor::color clr)
+       {
+               MapIt it = cache_.find(clr);
+               return it == cache_.end() ? 0 : it->second;
+       }
+       XftColor * getXftColor(LColor::color clr)
+       {
+               MapIt2 it = cache2_.find(clr);
+               return it == cache2_.end() ? 0 : it->second;
+       }
+       void cacheColor(LColor::color clr, Gdk::Color * gclr)
+       {
+               cache_[clr] = gclr;
+       }
+       void cacheXftColor(LColor::color clr, XftColor * xclr)
+       {
+               cache2_[clr] = xclr;
+       }
+       void clear();
+private:
+       Map cache_;
+       Map2 cache2_;
+};
+
+extern ColorCache colorCache;
+
+class ColorHandler
+{
+public:
+       ColorHandler(GWorkArea& owner) : owner_(owner) {}
+       XftColor * getXftColor(LColor::color clr);
+       Gdk::Color * getGdkColor(LColor::color clr);
+private:
+       GWorkArea & owner_;
+};
+
+class GWorkArea : public WorkArea, public SigC::Object
+{
+public:
+       GWorkArea(int width, int height);
+       ~GWorkArea();
+
+       virtual Painter & getPainter() { return painter_; }
+       ///
+       virtual int workWidth() const { return workArea_.get_width(); }
+       ///
+       virtual int workHeight() const { return workArea_.get_height(); }
+       /// return x position of window
+       int xpos() const { return 0; }
+       /// return y position of window
+       int ypos() const { return 0; }
+       ///
+       Glib::RefPtr<Gdk::Window> getWindow() { return workArea_.get_window(); }
+       Display * getDisplay() const
+       { return GDK_WINDOW_XDISPLAY(
+               const_cast<GdkWindow*>(workArea_.get_window()->gobj())); }
+       Glib::RefPtr<Gdk::Pixmap> getPixmap() { return workAreaPixmap_; }
+       Glib::RefPtr<Gdk::GC> getGC() { return workAreaGC_; }
+       Glib::RefPtr<Gdk::Colormap> getColormap() 
+       { return workArea_.get_colormap(); }
+       XftDraw * getXftDraw() { return draw_; }
+       ColorHandler & getColorHandler() { return colorHandler_; }
+
+       virtual void setScrollbarParams(int height, int pos, int line_height);
+       /// a selection exists
+       virtual void haveSelection(bool) const;
+       ///
+       virtual string const getClipboard() const;
+       ///
+       virtual void putClipboard(string const &) const;
+       void inputCommit(gchar * str);
+private:
+       bool onExpose(GdkEventExpose * event);
+       bool onConfigure(GdkEventConfigure * event);
+       void onScroll();
+       bool onButtonPress(GdkEventButton * event);
+       bool onButtonRelease(GdkEventButton * event);
+       bool onMotionNotify(GdkEventMotion * event);
+       bool onKeyPress(GdkEventKey * event);
+       void onClipboardGet(Gtk::SelectionData& selection_data, guint info);
+       void onClipboardClear();
+       Gtk::HBox hbox_;
+       Gtk::DrawingArea workArea_;
+       Gtk::VScrollbar vscrollbar_;
+       /// The pixmap overlay on the workarea
+       Glib::RefPtr<Gdk::Pixmap> workAreaPixmap_;
+       Glib::RefPtr<Gdk::GC> workAreaGC_;
+       /// the xforms-specific painter
+       GPainter painter_;
+       XftDraw * draw_;
+       ColorHandler colorHandler_;
+       GtkIMContext * imContext_;
+       string inputCache_;
+};
+
+#endif
diff --git a/src/frontends/gtk/GtkmmX.h b/src/frontends/gtk/GtkmmX.h
new file mode 100644 (file)
index 0000000..b236d7b
--- /dev/null
@@ -0,0 +1,64 @@
+// -*- C++ -*-
+/**
+ * \file GtkmmX.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef GTKMMX_H
+#define GTKMMX_H
+
+#include <X11/Xlib.h>
+#include <gtkmm.h>
+#include <gdk/gdkx.h>
+
+
+inline Display * getDisplay()
+{
+       return gdk_x11_get_default_xdisplay();
+}
+
+
+inline int getScreen()
+{
+       return gdk_x11_get_default_screen();
+}
+
+
+inline Window getRootWindow()
+{
+       static Window rootWin = 
+               GDK_WINDOW_XID(Gdk::Display::get_default()->
+                              get_default_screen()->
+                              get_root_window()->gobj());
+       return rootWin;
+}
+
+
+inline int getDepth()
+{
+       static int depth;
+       if (!depth) {
+               int width, height, x, y;
+               Gdk::Display::get_default()->get_default_screen()->
+                       get_root_window()->
+                       get_geometry(x, y, width, height, depth);
+       }
+       return depth;
+}
+
+
+inline Colormap getColormap()
+{
+       static Colormap colormap = GDK_COLORMAP_XCOLORMAP(
+               Gdk::Display::get_default()->get_default_screen()->
+               get_default_colormap()->gobj());
+       return colormap;
+}
+
+
+#endif
diff --git a/src/frontends/gtk/IdSc.C b/src/frontends/gtk/IdSc.C
new file mode 100644 (file)
index 0000000..9de4ce0
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * \file IdSc.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+
+#include "IdSc.h"
+#include "support/lstrings.h"
+
+using lyx::support::split;
+
+
+/// Extract shortcut from "<identifer>|#<shortcut>" string
+string const id_sc::shortcut(string const & idsc)
+{
+       string sc = split(idsc, '|');
+       if (!sc.empty() && sc[0] == '#')
+               sc.erase(sc.begin());
+       return sc;
+}
+
+
+/// Extract identifier from "<identifer>|#<shortcut>" string
+string const id_sc::id(string const & idsc)
+{
+       string id;
+       split(idsc, id, '|');
+       return id;
+}
diff --git a/src/frontends/gtk/IdSc.h b/src/frontends/gtk/IdSc.h
new file mode 100644 (file)
index 0000000..c203c87
--- /dev/null
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+/**
+ * \file IdSc.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef ID_SC_H
+#define ID_SC_H
+
+#include "LString.h"
+
+namespace id_sc
+{
+
+/// Extract shortcut from "<identifer>|<shortcut>" string
+string const shortcut(string const &);
+
+/// Extract identifier from "<identifer>|<shortcut>" string
+string const id(string const &);
+
+}
+
+#endif
diff --git a/src/frontends/gtk/LyXKeySymFactory.C b/src/frontends/gtk/LyXKeySymFactory.C
new file mode 100644 (file)
index 0000000..424ccbe
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * \file gtk/LyXKeySymFactory.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+
+#include "frontends/LyXKeySymFactory.h"
+
+#include "GLyXKeySym.h"
+
+
+namespace LyXKeySymFactory {
+
+
+LyXKeySym * create()
+{
+       return new GLyXKeySym();
+}
+
+
+}
diff --git a/src/frontends/gtk/LyXScreenFactory.C b/src/frontends/gtk/LyXScreenFactory.C
new file mode 100644 (file)
index 0000000..c4890f0
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * \file gtk/LyXScreenFactory.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+
+#include <gtkmm.h>
+#include "frontends/LyXScreenFactory.h"
+
+#include "GWorkArea.h"
+#include "GScreen.h"
+
+
+namespace LyXScreenFactory {
+
+
+LyXScreen * create(WorkArea & owner)
+{
+       return new GScreen(static_cast<GWorkArea &>(owner));
+}
+
+
+}
diff --git a/src/frontends/gtk/Makefile.am b/src/frontends/gtk/Makefile.am
new file mode 100644 (file)
index 0000000..69dbc16
--- /dev/null
@@ -0,0 +1,132 @@
+include $(top_srcdir)/config/common.am
+
+SUBDIRS = glade
+
+noinst_LTLIBRARIES = libgtk.la
+
+INCLUDES = -I$(top_srcdir)/images -I$(top_srcdir)/src \
+       -I$(top_srcdir)/src/frontends \
+       -I$(top_srcdir)/src/frontends/controllers \
+       -I$(top_srcdir)/src/frontends/xforms \
+       $(BOOST_INCLUDES) @GTK_FRONTEND_CFLAGS@
+
+libgtk_la_LIBADD = xforms.lo @GTK_FRONTEND_LIBS@ @XFORMS_LIBS@
+
+# Alphabetical order please.  It makes it easier to figure out what's missing.
+libgtk_la_SOURCES = \
+       lyx_gui.C \
+       GtkmmX.h \
+       xftFontLoader.C \
+       xftFontLoader.h \
+       codeConvert.h \
+       xftFontMetrics.C \
+       GScreen.C \
+       GScreen.h \
+       LyXScreenFactory.C \
+       GMenubar.C \
+       GMenubar.h \
+       GTimeout.C \
+       GTimeout.h \
+       GToolbar.C \
+       GToolbar.h \
+       WorkAreaFactory.C \
+       GMiniBuffer.C \
+       GMiniBuffer.h \
+       GPainter.C \
+       GPainter.h \
+       GWorkArea.h \
+       GWorkArea.C \
+       GLyXKeySym.h \
+       GLyXKeySym.C \
+       LyXKeySymFactory.C \
+       Alert_pimpl.C \
+       GView.h \
+       GView.C \
+       Dialogs.C \
+       GAboutlyx.h \
+       GAboutlyx.C \
+       GViewBase.h \
+       GViewBase.C \
+       GBC.h \
+       GBC.C \
+       FileDialogPrivate.h \
+       FileDialogPrivate.C \
+       FileDialog.C \
+       GText.h \
+       GText.C \
+       IdSc.h \
+       IdSc.C
+
+#      GPrint.h
+#      GPrint.C
+
+xforms_objects = \
+       ../xforms/bmtable.lo \
+       ../xforms/checkedwidgets.lo \
+       ../xforms/ColorHandler.lo \
+       ../xforms/Color.lo \
+       ../xforms/combox.lo \
+       ../xforms/Dialogs2.lo \
+       ../xforms/fdesign_base.lo \
+       ../xforms/FormBase.lo \
+       ../xforms/FormBibitem.lo \
+       ../xforms/FormBibtex.lo \
+       ../xforms/FormBranch.lo \
+       ../xforms/FormBrowser.lo \
+       ../xforms/FormChanges.lo \
+       ../xforms/FormCharacter.lo \
+       ../xforms/FormCitation.lo \
+       ../xforms/FormColorpicker.lo \
+       ../xforms/FormDialogView.lo \
+       ../xforms/FormDocument.lo \
+       ../xforms/FormErrorList.lo \
+       ../xforms/FormERT.lo \
+       ../xforms/FormExternal.lo \
+       ../xforms/FormFloat.lo \
+       ../xforms/FormForks.lo \
+       ../xforms/FormGraphics.lo \
+       ../xforms/FormInclude.lo \
+       ../xforms/FormLog.lo \
+       ../xforms/FormMathsBitmap.lo \
+       ../xforms/FormMathsDelim.lo \
+       ../xforms/FormMathsMatrix.lo \
+       ../xforms/FormMathsPanel.lo \
+       ../xforms/FormMathsSpace.lo \
+       ../xforms/FormMathsStyle.lo \
+       ../xforms/FormMinipage.lo \
+       ../xforms/FormNote.lo \
+       ../xforms/FormParagraph.lo \
+       ../xforms/FormPreamble.lo \
+       ../xforms/FormPreferences.lo \
+       ../xforms/FormPrint.lo \
+       ../xforms/FormRef.lo \
+       ../xforms/FormSearch.lo \
+       ../xforms/FormSendto.lo \
+       ../xforms/forms_gettext.lo \
+       ../xforms/FormShowFile.lo \
+       ../xforms/FormSpellchecker.lo \
+       ../xforms/FormTabularCreate.lo \
+       ../xforms/FormTabular.lo \
+       ../xforms/FormTexinfo.lo \
+       ../xforms/FormText.lo \
+       ../xforms/FormThesaurus.lo \
+       ../xforms/FormToc.lo \
+       ../xforms/FormUrl.lo \
+       ../xforms/FormVCLog.lo \
+       ../xforms/FormWrap.lo \
+       ../xforms/freebrowser.lo \
+       ../xforms/input_validators.lo \
+       ../xforms/RadioButtonGroup.lo \
+       ../xforms/Tooltips.lo \
+       ../xforms/xformsBC.lo \
+       ../xforms/xforms_helpers.lo \
+       ../xforms/xformsImage.lo \
+       ../xforms/xforms_resize.lo
+
+#      ../xforms/Dialogs.lo 
+#      ../xforms/FormFiledialog.lo 
+#      ../xforms/FileDialog.lo
+#      ../xforms/FormAboutlyx.lo
+
+xforms.lo: $(xforms_objects) ../xforms/forms/*.lo
+       $(CXXLINK) $(xforms_objects) ../xforms/forms/*.lo
diff --git a/src/frontends/gtk/WorkAreaFactory.C b/src/frontends/gtk/WorkAreaFactory.C
new file mode 100644 (file)
index 0000000..bf6c1b2
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * \file gtk/WorkAreaFactory.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "frontends/WorkAreaFactory.h"
+
+#include "GWorkArea.h"
+
+
+namespace WorkAreaFactory {
+
+
+WorkArea * create(int /*x*/, int /*y*/, int w, int h)
+{
+       return new GWorkArea(w, h);
+}
+
+
+}
diff --git a/src/frontends/gtk/codeConvert.h b/src/frontends/gtk/codeConvert.h
new file mode 100644 (file)
index 0000000..e9cb573
--- /dev/null
@@ -0,0 +1,36 @@
+// -*- C++ -*-
+/**
+ * \file codeConvert.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef CODE_CONVERT_H
+#define CODE_CONVERT_H
+
+#include <X11/Xft/Xft.h>
+
+
+inline FcChar32 * wcsToFcChar32StrFast(wchar_t * wcs)
+{
+       return reinterpret_cast<FcChar32*>(wcs);
+}
+
+
+inline FcChar32 const * wcsToFcChar32StrFast(wchar_t const * wcs)
+{
+       return reinterpret_cast<FcChar32 const *>(wcs);
+}
+
+
+inline FcChar32 wcToFcChar32(wchar_t wc)
+{
+       return static_cast<FcChar32>(wc);
+}
+
+
+#endif
diff --git a/src/frontends/gtk/glade/Makefile.am b/src/frontends/gtk/glade/Makefile.am
new file mode 100644 (file)
index 0000000..74195b5
--- /dev/null
@@ -0,0 +1,20 @@
+DISTCLEANFILES = *.orig *.rej *~ *.bak *.gladep
+MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
+
+GLADE_DIR = glade
+
+GLADE_FILES = *.glade
+
+EXTRA_DIST = ${GLADE_FILES}
+
+gladeinstalldirs:
+       $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)/${GLADE_DIR} ;
+
+install-data-local: gladeinstalldirs
+       files=`cd $(srcdir) ; echo $(GLADE_FILES)` ; \
+       for i in $${files} ; do \
+          $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(pkgdatadir)/${GLADE_DIR}/$$i ; \
+       done
+
+dist-hook:
+       cd $(distdir) ; rm -rf `find . -name \*CVS\*` ;
diff --git a/src/frontends/gtk/glade/aboutlyx.glade b/src/frontends/gtk/glade/aboutlyx.glade
new file mode 100644 (file)
index 0000000..c966986
--- /dev/null
@@ -0,0 +1,245 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkDialog" id="dialog">
+  <property name="title" translatable="yes">About LyX</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="default_width">300</property>
+  <property name="default_height">200</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+       <widget class="GtkHButtonBox" id="dialog-action_area1">
+         <property name="visible">True</property>
+         <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+         <child>
+           <widget class="GtkButton" id="close_button">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-close</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-7</property>
+           </widget>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">False</property>
+         <property name="fill">True</property>
+         <property name="pack_type">GTK_PACK_END</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkNotebook" id="notebook1">
+         <property name="visible">True</property>
+         <property name="can_focus">True</property>
+         <property name="show_tabs">True</property>
+         <property name="show_border">True</property>
+         <property name="tab_pos">GTK_POS_TOP</property>
+         <property name="scrollable">False</property>
+         <property name="enable_popup">False</property>
+
+         <child>
+           <widget class="GtkScrolledWindow" id="scrolledwindow3">
+             <property name="width_request">400</property>
+             <property name="height_request">250</property>
+             <property name="visible">True</property>
+             <property name="can_focus">True</property>
+             <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+             <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+             <property name="shadow_type">GTK_SHADOW_NONE</property>
+             <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+             <child>
+               <widget class="GtkViewport" id="viewport3">
+                 <property name="visible">True</property>
+                 <property name="shadow_type">GTK_SHADOW_IN</property>
+
+                 <child>
+                   <widget class="GtkLabel" id="version">
+                     <property name="visible">True</property>
+                     <property name="label" translatable="yes">version</property>
+                     <property name="use_underline">False</property>
+                     <property name="use_markup">False</property>
+                     <property name="justify">GTK_JUSTIFY_LEFT</property>
+                     <property name="wrap">True</property>
+                     <property name="selectable">False</property>
+                     <property name="xalign">0.5</property>
+                     <property name="yalign">0.5</property>
+                     <property name="xpad">0</property>
+                     <property name="ypad">0</property>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
+           </widget>
+           <packing>
+             <property name="tab_expand">False</property>
+             <property name="tab_fill">True</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkLabel" id="label6">
+             <property name="visible">True</property>
+             <property name="label" translatable="yes">Version</property>
+             <property name="use_underline">False</property>
+             <property name="use_markup">False</property>
+             <property name="justify">GTK_JUSTIFY_LEFT</property>
+             <property name="wrap">False</property>
+             <property name="selectable">False</property>
+             <property name="xalign">0.5</property>
+             <property name="yalign">0.5</property>
+             <property name="xpad">0</property>
+             <property name="ypad">0</property>
+           </widget>
+           <packing>
+             <property name="type">tab</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkScrolledWindow" id="scrolledwindow4">
+             <property name="width_request">400</property>
+             <property name="height_request">250</property>
+             <property name="visible">True</property>
+             <property name="can_focus">True</property>
+             <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+             <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+             <property name="shadow_type">GTK_SHADOW_NONE</property>
+             <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+             <child>
+               <widget class="GtkViewport" id="viewport4">
+                 <property name="visible">True</property>
+                 <property name="shadow_type">GTK_SHADOW_IN</property>
+
+                 <child>
+                   <widget class="GtkLabel" id="credits">
+                     <property name="visible">True</property>
+                     <property name="label" translatable="yes">credits</property>
+                     <property name="use_underline">False</property>
+                     <property name="use_markup">False</property>
+                     <property name="justify">GTK_JUSTIFY_LEFT</property>
+                     <property name="wrap">True</property>
+                     <property name="selectable">False</property>
+                     <property name="xalign">0.5</property>
+                     <property name="yalign">0.5</property>
+                     <property name="xpad">0</property>
+                     <property name="ypad">0</property>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
+           </widget>
+           <packing>
+             <property name="tab_expand">False</property>
+             <property name="tab_fill">True</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkLabel" id="label7">
+             <property name="visible">True</property>
+             <property name="label" translatable="yes">Credits</property>
+             <property name="use_underline">False</property>
+             <property name="use_markup">False</property>
+             <property name="justify">GTK_JUSTIFY_LEFT</property>
+             <property name="wrap">False</property>
+             <property name="selectable">False</property>
+             <property name="xalign">0.5</property>
+             <property name="yalign">0.5</property>
+             <property name="xpad">0</property>
+             <property name="ypad">0</property>
+           </widget>
+           <packing>
+             <property name="type">tab</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkScrolledWindow" id="scrolledwindow5">
+             <property name="width_request">400</property>
+             <property name="height_request">250</property>
+             <property name="visible">True</property>
+             <property name="can_focus">True</property>
+             <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+             <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+             <property name="shadow_type">GTK_SHADOW_NONE</property>
+             <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+             <child>
+               <widget class="GtkViewport" id="viewport5">
+                 <property name="visible">True</property>
+                 <property name="shadow_type">GTK_SHADOW_IN</property>
+
+                 <child>
+                   <widget class="GtkLabel" id="license">
+                     <property name="visible">True</property>
+                     <property name="label" translatable="yes">license</property>
+                     <property name="use_underline">False</property>
+                     <property name="use_markup">False</property>
+                     <property name="justify">GTK_JUSTIFY_LEFT</property>
+                     <property name="wrap">True</property>
+                     <property name="selectable">False</property>
+                     <property name="xalign">0.5</property>
+                     <property name="yalign">0.5</property>
+                     <property name="xpad">0</property>
+                     <property name="ypad">0</property>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
+           </widget>
+           <packing>
+             <property name="tab_expand">False</property>
+             <property name="tab_fill">True</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkLabel" id="label8">
+             <property name="visible">True</property>
+             <property name="label" translatable="yes">License</property>
+             <property name="use_underline">False</property>
+             <property name="use_markup">False</property>
+             <property name="justify">GTK_JUSTIFY_LEFT</property>
+             <property name="wrap">False</property>
+             <property name="selectable">False</property>
+             <property name="xalign">0.5</property>
+             <property name="yalign">0.5</property>
+             <property name="xpad">0</property>
+             <property name="ypad">0</property>
+           </widget>
+           <packing>
+             <property name="type">tab</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
diff --git a/src/frontends/gtk/glade/print.glade b/src/frontends/gtk/glade/print.glade
new file mode 100644 (file)
index 0000000..f8e8efb
--- /dev/null
@@ -0,0 +1,568 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkDialog" id="dialog">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">LyX:Print</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">False</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="has_separator">False</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+       <widget class="GtkHButtonBox" id="dialog-action_area1">
+         <property name="visible">True</property>
+         <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+         <child>
+           <widget class="GtkButton" id="CancelButton">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-cancel</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-6</property>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkButton" id="ApplyButton">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-apply</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-10</property>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkButton" id="OkButton">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-ok</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-5</property>
+           </widget>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">False</property>
+         <property name="fill">True</property>
+         <property name="pack_type">GTK_PACK_END</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkVBox" id="vbox1">
+         <property name="visible">True</property>
+         <property name="homogeneous">False</property>
+         <property name="spacing">0</property>
+
+         <child>
+           <widget class="GtkFrame" id="frame1">
+             <property name="visible">True</property>
+             <property name="label_xalign">0</property>
+             <property name="label_yalign">0.5</property>
+             <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+             <child>
+               <widget class="GtkTable" id="table1">
+                 <property name="border_width">5</property>
+                 <property name="visible">True</property>
+                 <property name="n_rows">3</property>
+                 <property name="n_columns">2</property>
+                 <property name="homogeneous">False</property>
+                 <property name="row_spacing">0</property>
+                 <property name="column_spacing">0</property>
+
+                 <child>
+                   <widget class="GtkHBox" id="hbox1">
+                     <property name="visible">True</property>
+                     <property name="homogeneous">False</property>
+                     <property name="spacing">0</property>
+
+                     <child>
+                       <widget class="GtkButton" id="Browse">
+                         <property name="visible">True</property>
+                         <property name="can_focus">True</property>
+                         <property name="label" translatable="yes">_Browse...</property>
+                         <property name="use_underline">True</property>
+                         <property name="relief">GTK_RELIEF_NORMAL</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">5</property>
+                         <property name="expand">False</property>
+                         <property name="fill">True</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <placeholder/>
+                     </child>
+                   </widget>
+                   <packing>
+                     <property name="left_attach">1</property>
+                     <property name="right_attach">2</property>
+                     <property name="top_attach">2</property>
+                     <property name="bottom_attach">3</property>
+                     <property name="y_padding">5</property>
+                     <property name="x_options">shrink|fill</property>
+                     <property name="y_options">fill</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkEntry" id="PrinterEntry">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="editable">True</property>
+                     <property name="visibility">True</property>
+                     <property name="max_length">0</property>
+                     <property name="text" translatable="yes"></property>
+                     <property name="has_frame">True</property>
+                     <property name="invisible_char" translatable="yes">*</property>
+                     <property name="activates_default">False</property>
+                   </widget>
+                   <packing>
+                     <property name="left_attach">1</property>
+                     <property name="right_attach">2</property>
+                     <property name="top_attach">0</property>
+                     <property name="bottom_attach">1</property>
+                     <property name="x_padding">5</property>
+                     <property name="y_padding">2</property>
+                     <property name="y_options"></property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkEntry" id="FileEntry">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="editable">True</property>
+                     <property name="visibility">True</property>
+                     <property name="max_length">0</property>
+                     <property name="text" translatable="yes"></property>
+                     <property name="has_frame">True</property>
+                     <property name="invisible_char" translatable="yes">*</property>
+                     <property name="activates_default">False</property>
+                   </widget>
+                   <packing>
+                     <property name="left_attach">1</property>
+                     <property name="right_attach">2</property>
+                     <property name="top_attach">1</property>
+                     <property name="bottom_attach">2</property>
+                     <property name="x_padding">5</property>
+                     <property name="y_padding">2</property>
+                     <property name="y_options"></property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkRadioButton" id="File">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">_File:</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                   </widget>
+                   <packing>
+                     <property name="left_attach">0</property>
+                     <property name="right_attach">1</property>
+                     <property name="top_attach">1</property>
+                     <property name="bottom_attach">2</property>
+                     <property name="x_padding">2</property>
+                     <property name="y_padding">2</property>
+                     <property name="x_options">fill</property>
+                     <property name="y_options"></property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkRadioButton" id="Printer">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">_Printer:</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                     <property name="group">File</property>
+                   </widget>
+                   <packing>
+                     <property name="left_attach">0</property>
+                     <property name="right_attach">1</property>
+                     <property name="top_attach">0</property>
+                     <property name="bottom_attach">1</property>
+                     <property name="x_padding">2</property>
+                     <property name="y_padding">2</property>
+                     <property name="x_options">fill</property>
+                     <property name="y_options"></property>
+                   </packing>
+                 </child>
+               </widget>
+             </child>
+
+             <child>
+               <widget class="GtkLabel" id="label1">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">Destination</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">False</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="type">label_item</property>
+               </packing>
+             </child>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">True</property>
+             <property name="fill">True</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkFrame" id="frame2">
+             <property name="visible">True</property>
+             <property name="label_xalign">0</property>
+             <property name="label_yalign">0.5</property>
+             <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+             <child>
+               <widget class="GtkVBox" id="vbox2">
+                 <property name="border_width">5</property>
+                 <property name="visible">True</property>
+                 <property name="homogeneous">False</property>
+                 <property name="spacing">10</property>
+
+                 <child>
+                   <widget class="GtkRadioButton" id="All">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">A_ll</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkHBox" id="hbox2">
+                     <property name="visible">True</property>
+                     <property name="homogeneous">False</property>
+                     <property name="spacing">0</property>
+
+                     <child>
+                       <widget class="GtkRadioButton" id="FromTo">
+                         <property name="visible">True</property>
+                         <property name="can_focus">True</property>
+                         <property name="label" translatable="yes">Fro_m:</property>
+                         <property name="use_underline">True</property>
+                         <property name="relief">GTK_RELIEF_NORMAL</property>
+                         <property name="active">False</property>
+                         <property name="inconsistent">False</property>
+                         <property name="draw_indicator">True</property>
+                         <property name="group">All</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkEntry" id="FromEntry">
+                         <property name="visible">True</property>
+                         <property name="can_focus">True</property>
+                         <property name="editable">True</property>
+                         <property name="visibility">True</property>
+                         <property name="max_length">5</property>
+                         <property name="text" translatable="yes"></property>
+                         <property name="has_frame">True</property>
+                         <property name="invisible_char" translatable="yes">*</property>
+                         <property name="activates_default">False</property>
+                         <property name="width_chars">5</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">10</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkLabel" id="label4">
+                         <property name="visible">True</property>
+                         <property name="label" translatable="yes">To:</property>
+                         <property name="use_underline">False</property>
+                         <property name="use_markup">False</property>
+                         <property name="justify">GTK_JUSTIFY_LEFT</property>
+                         <property name="wrap">False</property>
+                         <property name="selectable">False</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkEntry" id="ToEntry">
+                         <property name="visible">True</property>
+                         <property name="can_focus">True</property>
+                         <property name="editable">True</property>
+                         <property name="visibility">True</property>
+                         <property name="max_length">5</property>
+                         <property name="text" translatable="yes"></property>
+                         <property name="has_frame">True</property>
+                         <property name="invisible_char" translatable="yes">*</property>
+                         <property name="activates_default">False</property>
+                         <property name="width_chars">5</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">10</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">True</property>
+                     <property name="fill">True</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkCheckButton" id="Odd">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">_Odd numbered pages</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkCheckButton" id="Even">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">_Even numbered pages</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkCheckButton" id="Reverse">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">_Reverse order</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+               </widget>
+             </child>
+
+             <child>
+               <widget class="GtkLabel" id="label2">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">Pages</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">False</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="type">label_item</property>
+               </packing>
+             </child>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">True</property>
+             <property name="fill">True</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkFrame" id="frame3">
+             <property name="visible">True</property>
+             <property name="label_xalign">0</property>
+             <property name="label_yalign">0.5</property>
+             <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
+
+             <child>
+               <widget class="GtkHBox" id="hbox3">
+                 <property name="border_width">10</property>
+                 <property name="visible">True</property>
+                 <property name="homogeneous">True</property>
+                 <property name="spacing">5</property>
+
+                 <child>
+                   <widget class="GtkLabel" id="label5">
+                     <property name="visible">True</property>
+                     <property name="label" translatable="yes">Number</property>
+                     <property name="use_underline">False</property>
+                     <property name="use_markup">False</property>
+                     <property name="justify">GTK_JUSTIFY_LEFT</property>
+                     <property name="wrap">False</property>
+                     <property name="selectable">False</property>
+                     <property name="xalign">0.5</property>
+                     <property name="yalign">0.5</property>
+                     <property name="xpad">0</property>
+                     <property name="ypad">0</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkSpinButton" id="Number">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="climb_rate">1</property>
+                     <property name="digits">0</property>
+                     <property name="numeric">True</property>
+                     <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+                     <property name="snap_to_ticks">False</property>
+                     <property name="wrap">False</property>
+                     <property name="adjustment">1 0 100 1 10 10</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">True</property>
+                     <property name="fill">True</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkCheckButton" id="Sorted">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">_Sorted</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+               </widget>
+             </child>
+
+             <child>
+               <widget class="GtkLabel" id="label3">
+                 <property name="visible">True</property>
+                 <property name="label" translatable="yes">Copies</property>
+                 <property name="use_underline">False</property>
+                 <property name="use_markup">False</property>
+                 <property name="justify">GTK_JUSTIFY_LEFT</property>
+                 <property name="wrap">False</property>
+                 <property name="selectable">False</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xpad">0</property>
+                 <property name="ypad">0</property>
+               </widget>
+               <packing>
+                 <property name="type">label_item</property>
+               </packing>
+             </child>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">True</property>
+             <property name="fill">True</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
diff --git a/src/frontends/gtk/glade/text.glade b/src/frontends/gtk/glade/text.glade
new file mode 100644 (file)
index 0000000..ecc1661
--- /dev/null
@@ -0,0 +1,194 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkDialog" id="dialog">
+  <property name="visible">True</property>
+  <property name="title" translatable="yes">dialog1</property>
+  <property name="type">GTK_WINDOW_TOPLEVEL</property>
+  <property name="window_position">GTK_WIN_POS_NONE</property>
+  <property name="modal">False</property>
+  <property name="resizable">True</property>
+  <property name="destroy_with_parent">False</property>
+  <property name="has_separator">True</property>
+
+  <child internal-child="vbox">
+    <widget class="GtkVBox" id="dialog-vbox1">
+      <property name="visible">True</property>
+      <property name="homogeneous">False</property>
+      <property name="spacing">0</property>
+
+      <child internal-child="action_area">
+       <widget class="GtkHButtonBox" id="dialog-action_area1">
+         <property name="visible">True</property>
+         <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+         <child>
+           <widget class="GtkButton" id="Restore">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">0</property>
+
+             <child>
+               <widget class="GtkAlignment" id="alignment1">
+                 <property name="visible">True</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xscale">0</property>
+                 <property name="yscale">0</property>
+
+                 <child>
+                   <widget class="GtkHBox" id="hbox1">
+                     <property name="visible">True</property>
+                     <property name="homogeneous">False</property>
+                     <property name="spacing">2</property>
+
+                     <child>
+                       <widget class="GtkImage" id="image1">
+                         <property name="visible">True</property>
+                         <property name="stock">gtk-undo</property>
+                         <property name="icon_size">4</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkLabel" id="label1">
+                         <property name="visible">True</property>
+                         <property name="label" translatable="yes">_Restore</property>
+                         <property name="use_underline">True</property>
+                         <property name="use_markup">False</property>
+                         <property name="justify">GTK_JUSTIFY_LEFT</property>
+                         <property name="wrap">False</property>
+                         <property name="selectable">False</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkButton" id="Cancel">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-cancel</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-6</property>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkButton" id="Apply">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-apply</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-10</property>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkButton" id="OK">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="label">gtk-ok</property>
+             <property name="use_stock">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <property name="response_id">-5</property>
+           </widget>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">False</property>
+         <property name="fill">True</property>
+         <property name="pack_type">GTK_PACK_END</property>
+       </packing>
+      </child>
+
+      <child>
+       <widget class="GtkHBox" id="hbox2">
+         <property name="border_width">5</property>
+         <property name="visible">True</property>
+         <property name="homogeneous">False</property>
+         <property name="spacing">5</property>
+
+         <child>
+           <widget class="GtkLabel" id="Label">
+             <property name="visible">True</property>
+             <property name="label" translatable="yes">label</property>
+             <property name="use_underline">False</property>
+             <property name="use_markup">False</property>
+             <property name="justify">GTK_JUSTIFY_LEFT</property>
+             <property name="wrap">False</property>
+             <property name="selectable">False</property>
+             <property name="xalign">0.5</property>
+             <property name="yalign">0.5</property>
+             <property name="xpad">0</property>
+             <property name="ypad">0</property>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">False</property>
+             <property name="fill">False</property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkEntry" id="Text">
+             <property name="visible">True</property>
+             <property name="can_focus">True</property>
+             <property name="editable">True</property>
+             <property name="visibility">True</property>
+             <property name="max_length">0</property>
+             <property name="text" translatable="yes"></property>
+             <property name="has_frame">True</property>
+             <property name="invisible_char" translatable="yes">*</property>
+             <property name="activates_default">False</property>
+           </widget>
+           <packing>
+             <property name="padding">0</property>
+             <property name="expand">True</property>
+             <property name="fill">True</property>
+           </packing>
+         </child>
+       </widget>
+       <packing>
+         <property name="padding">0</property>
+         <property name="expand">True</property>
+         <property name="fill">True</property>
+       </packing>
+      </child>
+    </widget>
+  </child>
+</widget>
+
+</glade-interface>
diff --git a/src/frontends/gtk/lyx_gui.C b/src/frontends/gtk/lyx_gui.C
new file mode 100644 (file)
index 0000000..680f93d
--- /dev/null
@@ -0,0 +1,454 @@
+/**
+ * \file gtk/lyx_gui.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Lars Gullik Bjnes
+ * \author John Levon
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include "lyx_gui.h"
+
+#include "support/lyxlib.h"
+#include "support/os.h"
+#include "support/filetools.h"
+#include "support/path_defines.h"
+
+#include "debug.h"
+#include "gettext.h"
+
+#include "lyx_main.h"
+#include "lyxrc.h"
+#include "lyxfont.h"
+#include "graphics/LoaderQueue.h"
+
+// FIXME: move this stuff out again
+#include "bufferlist.h"
+#include "buffer_funcs.h"
+#include "lyxfunc.h"
+#include "lyxserver.h"
+#include "BufferView.h"
+
+#include "GView.h"
+#include "GtkmmX.h"
+
+#include "xftFontLoader.h"
+#include "GWorkArea.h"
+
+#include "Lsstream.h"
+#include <iomanip>
+#include <fcntl.h>
+#include <boost/bind.hpp>
+
+//just for xforms
+#include "lyx_forms.h"
+#include "xformsImage.h"
+#include "xforms_helpers.h"
+
+extern BufferList bufferlist;
+
+// FIXME: wrong place !
+LyXServer * lyxserver;
+
+bool lyx_gui::use_gui = true;
+
+namespace {
+
+/// quit lyx
+bool finished = false;
+
+
+/// estimate DPI from X server
+float getDPI()
+{
+       Screen * scr = ScreenOfDisplay(getDisplay(), getScreen());
+       return ((HeightOfScreen(scr) * 25.4 / HeightMMOfScreen(scr)) +
+               (WidthOfScreen(scr) * 25.4 / WidthMMOfScreen(scr))) / 2;
+}
+
+
+/// set default GUI configuration
+void setDefaults()
+{
+       FL_IOPT cntl;
+       cntl.buttonFontSize = FL_NORMAL_SIZE;
+       cntl.browserFontSize = FL_NORMAL_SIZE;
+       cntl.labelFontSize = FL_NORMAL_SIZE;
+       cntl.choiceFontSize = FL_NORMAL_SIZE;
+       cntl.inputFontSize = FL_NORMAL_SIZE;
+       cntl.menuFontSize  = FL_NORMAL_SIZE;
+       cntl.borderWidth = -1;
+       cntl.vclass = FL_DefaultVisual;
+       fl_set_defaults(FL_PDVisual
+                       | FL_PDButtonFontSize
+                       | FL_PDBrowserFontSize
+                       | FL_PDLabelFontSize
+                       | FL_PDChoiceFontSize
+                       | FL_PDInputFontSize
+                       | FL_PDMenuFontSize
+                       | FL_PDBorderWidth, &cntl);
+}
+
+
+extern "C" {
+
+
+int LyX_XErrHandler(Display * display, XErrorEvent * xeev) {
+       // We don't abort on BadWindow
+       if (xeev->error_code == BadWindow) {
+               lyxerr << "BadWindow received !" << std::endl;
+               lyxerr << "If you're using xforms 1.0 or greater, "
+                      << " please report this to lyx-devel@lists.lyx.org" 
+                      << std::endl;
+               return 0;
+       }
+
+       // emergency cleanup
+       LyX::emergencyCleanup();
+
+       // Get the reason for the crash.
+       char etxt[513];
+       XGetErrorText(display, xeev->error_code, etxt, 512);
+       lyxerr << etxt << " id: " << xeev->resourceid << std::endl;
+       // By doing an abort we get a nice backtrace. (hopefully)
+       lyx::support::abort();
+       return 0;
+}
+
+}
+
+/// read in geometry specification
+char geometry[40];
+
+} // namespace anon
+
+
+void parse_init_xforms(int & argc, char * argv[])
+{
+       setDefaults();
+
+       FL_CMD_OPT cmdopt[] = {
+               {"-geometry", "*.geometry", XrmoptionSepArg, "690x510"}
+       };
+
+       FL_resource res[] = {
+               {"geometry", "geometryClass", FL_STRING, geometry, "", 40}
+       };
+
+       const int num_res = sizeof(res)/sizeof(FL_resource);
+       fl_initialize(&argc, argv, "LyX", cmdopt, num_res);
+
+       // It appears that, in xforms >=0.89.5, fl_initialize()
+       // calls setlocale() and ruins our LC_NUMERIC setting.
+
+       fl_get_app_resources(res, num_res);
+
+       Display * display = fl_get_display();
+
+       if (!display) {
+               lyxerr << "LyX: unable to access X display, exiting"
+                      << std::endl;
+               lyx::support::os::warn("Unable to access X display, exiting");
+               ::exit(1);
+       }
+
+       fcntl(ConnectionNumber(display), F_SETFD, FD_CLOEXEC);
+
+       XSetErrorHandler(LyX_XErrHandler);
+
+       using namespace lyx::graphics;
+
+       // connect the image loader based on the xforms library
+       Image::newImage = boost::bind(&xformsImage::newImage);
+       Image::loadableFormats = boost::bind(&xformsImage::loadableFormats);
+}
+
+
+void lyx_gui::parse_init(int & argc, char * argv[])
+{
+       new Gtk::Main(argc, argv);
+
+       parse_init_xforms(argc, argv);
+
+       locale_init();
+
+       // must do this /before/ lyxrc gets read
+       lyxrc.dpi = getDPI();
+}
+
+
+void parse_lyxrc_xforms()
+{
+       XformsColor::read(lyx::support::AddName(
+                                 lyx::support::user_lyxdir(), "preferences.xform"));
+
+       if (lyxrc.popup_font_encoding.empty())
+               lyxrc.popup_font_encoding = lyxrc.font_norm;
+       // Set the font name for popups and menus
+       string boldfontname = lyxrc.popup_bold_font
+                              + "-*-*-*-?-*-*-*-*-"
+                              + lyxrc.popup_font_encoding;
+               // "?" means "scale that font"
+       string fontname = lyxrc.popup_normal_font
+                              + "-*-*-*-?-*-*-*-*-"
+                              + lyxrc.popup_font_encoding;
+
+       int bold = fl_set_font_name(FL_BOLD_STYLE, boldfontname.c_str());
+       int normal = fl_set_font_name(FL_NORMAL_STYLE, fontname.c_str());
+       if (bold < 0)
+               lyxerr << "Could not set menu font to "
+                      << boldfontname << std::endl;
+
+       if (normal < 0)
+               lyxerr << "Could not set popup font to "
+                      << fontname << std::endl;
+
+       if (bold < 0 && normal < 0) {
+               lyxerr << "Using 'helvetica' font for menus" << std::endl;
+               boldfontname = "-*-helvetica-bold-r-*-*-*-?-*-*-*-*-iso8859-1";
+               fontname = "-*-helvetica-medium-r-*-*-*-?-*-*-*-*-iso8859-1";
+               bold = fl_set_font_name(FL_BOLD_STYLE, boldfontname.c_str());
+               normal = fl_set_font_name(FL_NORMAL_STYLE, fontname.c_str());
+
+               if (bold < 0 && normal < 0) {
+                       lyxerr << "Could not find helvetica font. Using 'fixed'."
+                              << std::endl;
+                       fl_set_font_name(FL_NORMAL_STYLE, "fixed");
+                       normal = bold = 0;
+               }
+       }
+       if (bold < 0)
+               fl_set_font_name(FL_BOLD_STYLE, fontname.c_str());
+       else if (normal < 0)
+               fl_set_font_name(FL_NORMAL_STYLE, boldfontname.c_str());
+
+       fl_setpup_fontstyle(FL_NORMAL_STYLE);
+       fl_setpup_fontsize(FL_NORMAL_SIZE);
+       fl_setpup_color(FL_MCOL, FL_BLACK);
+       fl_set_goodies_font(FL_NORMAL_STYLE, FL_NORMAL_SIZE);
+       fl_set_tooltip_font(FL_NORMAL_STYLE, FL_NORMAL_SIZE);
+}
+
+
+void lyx_gui::parse_lyxrc()
+{
+       parse_lyxrc_xforms();
+}
+
+
+void start_xforms()
+{
+       // initial geometry
+       int xpos = -1;
+       int ypos = -1;
+       unsigned int width = 690;
+       unsigned int height = 510;
+
+       int const geometryBitmask =
+               XParseGeometry(geometry,
+                              &xpos, &ypos, &width, &height);
+
+       // if width is not set by geometry, check it against monitor width
+       if (!(geometryBitmask & WidthValue)) {
+               Screen * scr = ScreenOfDisplay(fl_get_display(), fl_screen);
+               if (WidthOfScreen(scr) - 8 < int(width))
+                       width = WidthOfScreen(scr) - 8;
+       }
+
+       // if height is not set by geometry, check it against monitor height
+       if (!(geometryBitmask & HeightValue)) {
+               Screen * scr = ScreenOfDisplay(fl_get_display(), fl_screen);
+               if (HeightOfScreen(scr) - 24 < int(height))
+                       height = HeightOfScreen(scr) - 24;
+       }
+
+       Screen * s = ScreenOfDisplay(fl_get_display(), fl_screen);
+
+       // recalculate xpos if it's not set
+       if (xpos == -1)
+               xpos = (WidthOfScreen(s) - width) / 2;
+
+       // recalculate ypos if it's not set
+       if (ypos == -1)
+               ypos = (HeightOfScreen(s) - height) / 2;
+
+       lyxerr[Debug::GUI] << "Creating view: " << width << 'x' << height
+                          << '+' << xpos << '+' << ypos << std::endl;
+
+//     XFormsView view(width, height);
+//     view.show(xpos, ypos, "LyX");
+//     view.init();
+}
+
+
+static void events_xforms()
+{
+       if (fl_check_forms() == FL_EVENT) {
+               XEvent ev;
+               fl_XNextEvent(&ev);
+               lyxerr[Debug::GUI]
+                       << "Received unhandled X11 event" << std::endl
+                       << "Type: " << ev.xany.type
+                       << " Target: 0x" << std::hex << ev.xany.window
+                       << std::dec << std::endl;
+       }
+}
+
+
+void lyx_gui::start(string const & batch, std::vector<string> const & files)
+{
+       start_xforms();
+       // just for debug
+       XSynchronize(getDisplay(), true);
+       GView view;
+       view.show();
+       view.init();
+
+       Buffer * last = 0;
+
+       // FIXME: some code below needs moving
+
+       lyxserver = new LyXServer(&view.getLyXFunc(), lyxrc.lyxpipes);
+
+       std::vector<string>::const_iterator cit = files.begin();
+       std::vector<string>::const_iterator end = files.end();
+       for (; cit != end; ++cit) {
+               Buffer * b = bufferlist.newBuffer(*cit);
+               if (loadLyXFile(b, *cit))
+                       last = b;
+       }
+
+       // switch to the last buffer successfully loaded
+       if (last) {
+               view.view()->buffer(last);
+       }
+
+       // handle the batch commands the user asked for
+       if (!batch.empty()) {
+               view.getLyXFunc().dispatch(batch);
+       }
+
+       // enter the event loop
+       while (!finished) {
+               while (Gtk::Main::events_pending())
+                       Gtk::Main::iteration(false);
+               events_xforms();
+       }
+
+       // FIXME: breaks emergencyCleanup
+       delete lyxserver;
+}
+
+
+void lyx_gui::exit()
+{
+       finished = true;
+}
+
+
+FuncStatus lyx_gui::getStatus(FuncRequest const & /*ev*/)
+{
+       // Nothing interesting to do here
+       return FuncStatus();
+}
+
+
+string const lyx_gui::hexname(LColor::color col)
+{
+       Gdk::Color gdkColor;
+       Gdk::Color * gclr = colorCache.getColor(col);
+       if (!gclr) {
+               gclr = &gdkColor;
+               gclr->parse(lcolor.getX11Name(col));
+       }
+
+       std::ostringstream os;
+
+       // Note that X stores the RGB values in the range 0 - 65535
+       // whilst we require them in the range 0 - 255.
+       os << std::setbase(16) << std::setfill('0')
+          << std::setw(2) << (gclr->get_red() / 256)
+          << std::setw(2) << (gclr->get_green() / 256)
+          << std::setw(2) << (gclr->get_blue() / 256);
+
+       return os.str();
+}
+
+
+void lyx_gui::update_color(LColor::color /*col*/)
+{
+       colorCache.clear();
+}
+
+
+void lyx_gui::update_fonts()
+{
+       fontLoader.update();
+}
+
+
+bool lyx_gui::font_available(LyXFont const & font)
+{
+       return fontLoader.available(font);
+}
+
+
+namespace {
+
+
+bool readCallback(Glib::IOCondition /*condition*/, LyXComm * comm)
+{
+       comm->read_ready();
+       return true;
+}
+
+
+std::map<int, SigC::Connection> gReadCallbackMap;
+
+}
+
+
+void lyx_gui::set_read_callback(int fd, LyXComm * comm)
+{
+       gReadCallbackMap[fd] = Glib::signal_io().connect(
+               SigC::bind(SigC::slot(readCallback), comm),
+               fd,
+               Glib::IO_IN);
+}
+
+
+void lyx_gui::remove_read_callback(int fd)
+{
+       gReadCallbackMap[fd].disconnect();
+       gReadCallbackMap.erase(fd);
+}
+
+
+string const lyx_gui::roman_font_name()
+{
+       return "times";
+}
+
+
+string const lyx_gui::sans_font_name()
+{
+       return "helvetica";
+}
+
+
+string const lyx_gui::typewriter_font_name()
+{
+       return "courier";
+}
+
+
+void lyx_gui::sync_events()
+{
+       // FIXME
+}
diff --git a/src/frontends/gtk/xftFontLoader.C b/src/frontends/gtk/xftFontLoader.C
new file mode 100644 (file)
index 0000000..12ddbbd
--- /dev/null
@@ -0,0 +1,213 @@
+/**
+ * \file xftFontLoader.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+#include <cmath>       // fabs()
+
+#include <X11/Xft/Xft.h>
+#include "xftFontLoader.h"
+#include "FontInfo.h"
+#include "gettext.h"
+#include "debug.h"
+#include "lyxrc.h"     // lyxrc.font_*
+#include "BufferView.h"
+#include "frontends/LyXView.h"
+#include "support/systemcall.h"
+#include "support/filetools.h"
+#include "GtkmmX.h"
+#include <vector>
+#include "frontends/lyx_gui.h"
+
+using std::endl;
+
+// The global fontLoader
+xftFontLoader fontLoader;
+
+
+// Initialize font loader
+xftFontLoader::xftFontLoader()
+{
+}
+
+
+// Destroy font loader
+xftFontLoader::~xftFontLoader()
+{
+       unload();
+}
+
+
+// Update fonts after zoom, dpi, font names, or norm change
+// For now, we just ditch all fonts we have. Later, we should
+// reuse the ones that are already loaded.
+void xftFontLoader::update()
+{
+       unload();
+}
+
+
+// Unload all fonts
+void xftFontLoader::unload()
+{
+       // Unload all fonts
+       for (int i1 = 0; i1 < LyXFont::NUM_FAMILIES; ++i1)
+               for (int i2 = 0; i2 < 2; ++i2)
+                       for (int i3 = 0; i3 < 4; ++i3)
+                               for (int i4 = 0; i4 < 10; ++i4) {
+                                       if (fonts_[i1][i2][i3][i4]){
+                                               XftFontClose(getDisplay(), fonts_[i1][i2][i3][i4]);
+                                               fonts_[i1][i2][i3][i4] = 0;
+                                       }
+                               }
+}
+
+
+string xftFontLoader::familyString(LyXFont::FONT_FAMILY family)
+{
+       string ffamily;
+       switch (family) {
+       case LyXFont::ROMAN_FAMILY:
+               ffamily = lyxrc.roman_font_name;
+               break;
+       case LyXFont::SANS_FAMILY:
+               ffamily = lyxrc.sans_font_name;
+               break;
+       case LyXFont::TYPEWRITER_FAMILY:
+               ffamily = lyxrc.typewriter_font_name;
+               break;
+       case LyXFont::CMR_FAMILY:
+               ffamily = "cmr10";
+               break;
+       case LyXFont::CMSY_FAMILY:
+               ffamily = "cmsy10";
+               break;
+       case LyXFont::CMM_FAMILY:
+               ffamily = "cmmi10";
+               break;
+       case LyXFont::CMEX_FAMILY:
+               ffamily = "cmex10";
+               break;
+       case LyXFont::MSA_FAMILY:
+               ffamily = "msam10";
+               break;
+       case LyXFont::MSB_FAMILY:
+               ffamily = "msbm10";
+               break;
+       default:
+               ffamily = "Sans";
+               break;
+       }
+       return ffamily;
+}
+
+
+// Get font pattern
+/* Takes care of finding which font that can match the given request. Tries
+different alternatives. */
+XftPattern * xftFontLoader::getFontPattern(LyXFont::FONT_FAMILY family,
+                                         LyXFont::FONT_SERIES series,
+                                         LyXFont::FONT_SHAPE shape,
+                                         LyXFont::FONT_SIZE size)
+{
+       // Normal font. Let's search for an existing name that matches.
+       string ffamily;
+       int fweight;
+       int fslant;
+       double fsize = lyxrc.font_sizes[size] * lyxrc.zoom / 100.0;
+       XftPattern *fpat = XftPatternCreate();
+
+       ffamily = familyString(family);
+       switch (series) {
+       case LyXFont::MEDIUM_SERIES:
+               fweight = XFT_WEIGHT_MEDIUM;
+               break;
+       case LyXFont::BOLD_SERIES:
+               fweight = XFT_WEIGHT_BOLD;
+               break;
+       default: 
+               fweight = XFT_WEIGHT_MEDIUM;
+               break;
+       }
+
+       switch (shape) {
+       case LyXFont::UP_SHAPE:
+       case LyXFont::SMALLCAPS_SHAPE:
+               fslant = XFT_SLANT_ROMAN;
+               break;
+       case LyXFont::ITALIC_SHAPE:
+               fslant = XFT_SLANT_ITALIC;
+               break;
+       case LyXFont::SLANTED_SHAPE:
+               fslant = XFT_SLANT_OBLIQUE;
+               break;
+       default: 
+               fslant = XFT_SLANT_ROMAN;
+               break;
+       }
+       XftPatternAddString(fpat, XFT_FAMILY, ffamily.c_str());
+       XftPatternAddInteger(fpat, XFT_WEIGHT, fweight);
+       XftPatternAddInteger(fpat, XFT_SLANT, fslant);
+       XftPatternAddDouble(fpat, XFT_SIZE, fsize);
+       return fpat;
+}
+
+
+/// Do load font
+XftFont * xftFontLoader::doLoad(LyXFont::FONT_FAMILY family,
+                              LyXFont::FONT_SERIES series,
+                              LyXFont::FONT_SHAPE shape,
+                              LyXFont::FONT_SIZE size)
+{
+       XftPattern *fpat = getFontPattern(family, series, shape, size);
+       XftResult result;
+       XftPattern *fpat2 = XftFontMatch(getDisplay(), getScreen(),
+                                        fpat, &result);
+       XftFont * font = XftFontOpenPattern(getDisplay(), fpat2);
+       fonts_[family][series][shape][size] = font;
+       return font;
+}
+
+
+bool xftFontLoader::available(LyXFont const & f)
+{
+       if (!lyx_gui::use_gui)
+               return false;
+
+       static std::vector<bool> cache_set(LyXFont::NUM_FAMILIES, false);
+       static std::vector<bool> cache(LyXFont::NUM_FAMILIES, false);
+
+       LyXFont::FONT_FAMILY family = f.family();
+       if (cache_set[family])
+               return cache[family];
+       cache_set[family] = true;
+
+       string const ffamily = familyString(family);
+       if (isSpecial(f)) {
+               cache_set[family] = true;
+               XftPattern *fpat = XftPatternCreate();
+               XftPatternAddString(fpat, XFT_FAMILY, ffamily.c_str());
+               XftResult result;
+               XftPattern *fpat2 = XftFontMatch(getDisplay(), getScreen(),
+                                                fpat, &result);
+               XftPatternDestroy(fpat);
+               char * familyM;
+               XftPatternGetString(fpat2, XFT_FAMILY, 0, &familyM);
+               if (ffamily == familyM) {
+                       cache[family] = true;
+                       return true;
+               }
+               // We don't need to set cache[family] to false, as it
+               // is initialized to false;
+               return false;
+       }
+       // We don't care about non-symbol fonts
+       return false;
+}
diff --git a/src/frontends/gtk/xftFontLoader.h b/src/frontends/gtk/xftFontLoader.h
new file mode 100644 (file)
index 0000000..9194ae6
--- /dev/null
@@ -0,0 +1,81 @@
+// -*- C++ -*-
+/**
+ * \file xftFontLoader.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#ifndef XFT_FONT_LOADER_H
+#define XFT_FONT_LOADER_H
+
+#include "lyxfont.h"
+#include "LString.h"
+#include <X11/Xft/Xft.h>
+
+class GWorkArea;
+
+
+class xftFontLoader {
+public:
+       ///
+       xftFontLoader();
+
+       ///
+       ~xftFontLoader();
+
+       /// Update fonts after zoom, dpi, font names, or norm change
+       void update();
+
+       bool available(LyXFont const & f);
+
+       /// Load font
+       XftFont * load(LyXFont::FONT_FAMILY family,
+                     LyXFont::FONT_SERIES series,
+                     LyXFont::FONT_SHAPE shape,
+                     LyXFont::FONT_SIZE size)
+       {
+                if (fonts_[family][series][shape][size])
+                        return fonts_[family][series][shape][size];
+                else
+                       return doLoad(family, series, shape, size);
+        }
+       bool isSpecial(LyXFont const & f)
+       {
+               switch (f.family()) {
+               case LyXFont::CMR_FAMILY:
+               case LyXFont::EUFRAK_FAMILY:
+                       return true;
+               default:
+                       break;
+               }
+               return f.isSymbolFont();
+       }
+private:
+       /// Array of fonts
+       XftFont * fonts_[LyXFont::NUM_FAMILIES][2][4][10];
+       XftPattern * getFontPattern(LyXFont::FONT_FAMILY family,
+                                   LyXFont::FONT_SERIES series,
+                                   LyXFont::FONT_SHAPE shape,
+                                   LyXFont::FONT_SIZE size);
+       string familyString(LyXFont::FONT_FAMILY family);
+       /// Reset font handler
+       void reset();
+
+       /// Unload all fonts
+       void unload();
+
+       /** Does the actual loading of a font. Updates fontstruct. */
+       XftFont * doLoad(LyXFont::FONT_FAMILY family,
+                         LyXFont::FONT_SERIES series,
+                         LyXFont::FONT_SHAPE shape,
+                         LyXFont::FONT_SIZE size);
+};
+
+///
+extern xftFontLoader fontLoader;
+
+#endif
diff --git a/src/frontends/gtk/xftFontMetrics.C b/src/frontends/gtk/xftFontMetrics.C
new file mode 100644 (file)
index 0000000..dd10bd5
--- /dev/null
@@ -0,0 +1,265 @@
+/**
+ * \file xfont_metrics.C
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Huang Ying
+ *
+ * Full author contact details are available in file CREDITS
+ */
+
+#include <config.h>
+#include <gtkmm.h>
+
+#include <algorithm>
+#include "GtkmmX.h"
+#include "support/lstrings.h"
+#include "xftFontLoader.h"
+#include "font_metrics.h"
+#include "lyxrc.h"
+#include "encoding.h"
+#include "language.h"
+#include "codeConvert.h"
+
+#include <boost/scoped_array.hpp>
+
+
+namespace {
+
+
+inline XftFont * getXftFont(LyXFont const & f)
+{
+       return fontLoader.load(f.family(), f.series(),
+                              f.realShape(), f.size());
+}
+
+
+inline int XGlyphAscent(XGlyphInfo const & info)
+{
+       return info.y;
+}
+
+
+inline int XGlyphDescent(XGlyphInfo const & info)
+{
+       return info.height - info.y;
+}
+
+
+inline int XGlyphLbearing(XGlyphInfo const & info)
+{
+       return -info.x;
+}
+
+
+inline int XGlyphRbearing(XGlyphInfo const & info)
+{
+       return -info.x + info.width;
+}
+
+
+inline int XGlyphLogWidth(XGlyphInfo const & info)
+{
+       return info.xOff;
+}
+
+
+wchar_t C2WC(char ch)
+{
+       wchar_t wcs[2] = {0, 0};
+       char mbs[2] = {0, 0};
+       mbs[0] = ch;
+       mbstowcs(wcs, mbs, 2);
+       return wcs[0];
+}
+
+
+} // namespace anon
+
+
+namespace font_metrics {
+
+
+int maxAscent(LyXFont const & f)
+{
+       XftFont * font = getXftFont(f);
+       return font->ascent;
+}
+
+
+int maxDescent(LyXFont const & f)
+{
+       XftFont * font = getXftFont(f);
+       return font->descent;
+}
+
+
+int ascent(wchar_t c,LyXFont const & f)
+{
+       XftFont * font = getXftFont(f);
+       XGlyphInfo glyph;
+       XftTextExtents32(getDisplay(), font,
+                        wcsToFcChar32StrFast(&c),
+                        1,
+                        &glyph);
+       return XGlyphAscent(glyph);
+}
+
+
+int ascent(char c, LyXFont const & f)
+{
+       return ascent(C2WC(c), f);
+}
+
+
+int descent(wchar_t c,LyXFont const & f)
+{
+       XftFont * font = getXftFont(f);
+       XGlyphInfo glyph;
+       XftTextExtents32(getDisplay(), font,
+                        wcsToFcChar32StrFast(&c),
+                        1,
+                        &glyph);
+       return XGlyphDescent(glyph);
+}
+
+
+int descent(char c, LyXFont const & f)
+{
+       return descent(C2WC(c), f);
+}
+
+
+int lbearing(wchar_t c,LyXFont const & f)
+ {
+       XftFont * font = getXftFont(f);
+       XGlyphInfo glyph;
+       XftTextExtents32(getDisplay(), font,
+                        wcsToFcChar32StrFast(&c),
+                        1,
+                        &glyph);
+       return XGlyphLbearing(glyph);
+ }
+
+
+int rbearing(wchar_t c,LyXFont const & f)
+{
+       XftFont * font = getXftFont(f);
+       XGlyphInfo glyph;
+       XftTextExtents32(getDisplay(), font,
+                        wcsToFcChar32StrFast(&c),
+                        1,
+                        &glyph);
+       return XGlyphRbearing(glyph);
+}
+
+
+int lbearing(char c, LyXFont const & f)
+{
+       return lbearing(C2WC(c), f);
+}
+
+
+int rbearing(char c, LyXFont const & f)
+{
+       return rbearing(C2WC(c), f);
+}
+
+
+int width(wchar_t const * s, size_t n, LyXFont const & f)
+{
+       XftFont * font = getXftFont(f);
+       XGlyphInfo glyph;
+       if (f.realShape() != LyXFont::SMALLCAPS_SHAPE){
+               XftTextExtents32(getDisplay(), font,
+                                wcsToFcChar32StrFast(s),
+                                n,
+                                &glyph);
+               return XGlyphLogWidth(glyph);
+       } else {
+               int result = 0;
+               LyXFont smallfont(f);
+               smallfont.decSize().decSize().setShape(LyXFont::UP_SHAPE);
+               XftFont * fontS = getXftFont(smallfont);
+               for (size_t i = 0; i < n; ++i) {
+                       wchar_t wc = lyx::support::uppercase(s[i]);
+                       if (wc != s[i]) {
+                               XftTextExtents32(getDisplay(), fontS,
+                                                wcsToFcChar32StrFast(&wc),
+                                                1,
+                                                &glyph);
+                               result += XGlyphLogWidth(glyph);
+                       } else {
+                               XftTextExtents32(getDisplay(), font,
+                                                wcsToFcChar32StrFast(&wc),
+                                                1,
+                                                &glyph);
+                               result += XGlyphLogWidth(glyph);
+                       }
+               }
+               return result;
+       }
+}
+
+
+int width(wchar_t c,LyXFont const & f)
+{
+       return width(&c, 1, f);
+}
+
+
+int width(char const * s, size_t n,LyXFont const & f)
+{
+       boost::scoped_array<wchar_t> wcs(new wchar_t[n]);
+       size_t len;
+       if (fontLoader.isSpecial(f)) {
+               unsigned char const * us =
+                       reinterpret_cast<unsigned char const *>(s);
+               len = n;
+               std::copy(us, us + n, wcs.get());
+       } else
+               len = mbstowcs(wcs.get(), s, n);
+       return width(wcs.get(), len, f);
+}
+
+
+int signedWidth(string const & s, LyXFont const & f)
+{
+       if (s.empty())
+               return 0;
+       boost::scoped_array<wchar_t> wcs(new wchar_t[s.length() + 1]);
+       int len = mbstowcs(wcs.get(), s.c_str(), s.length());
+       if (wcs[0] == '-')
+               return width(wcs.get() + 1, len - 1, f);
+       else
+               return width(wcs.get(), len, f);
+}
+
+
+void rectText(string const & str, LyXFont const & font,
+       int & width,
+       int & ascent,
+       int & descent)
+{
+       static int const d = 2;
+       width = font_metrics::width(str, font) + d * 2 + 2;
+       ascent = font_metrics::maxAscent(font) + d;
+       descent = font_metrics::maxDescent(font) + d;
+}
+
+
+void buttonText(string const & str, LyXFont const & font,
+       int & width,
+       int & ascent,
+       int & descent)
+{
+       static int const d = 3;
+
+       width = font_metrics::width(str, font) + d * 2 + 2;
+       ascent = font_metrics::maxAscent(font) + d;
+       descent = font_metrics::maxDescent(font) + d;
+}
+
+
+} // namespace font_metrics
+