]> git.lyx.org Git - features.git/commitdiff
The new combox code.
authorAngus Leeming <leeming@lyx.org>
Wed, 2 Apr 2003 14:20:30 +0000 (14:20 +0000)
committerAngus Leeming <leeming@lyx.org>
Wed, 2 Apr 2003 14:20:30 +0000 (14:20 +0000)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@6681 a592a061-630c-0410-9148-cb99ea01b6c8

28 files changed:
src/frontends/xforms/ChangeLog
src/frontends/xforms/Dialogs2.C
src/frontends/xforms/DropDown.C [deleted file]
src/frontends/xforms/DropDown.h [deleted file]
src/frontends/xforms/FormCharacter.C
src/frontends/xforms/FormCharacter.h
src/frontends/xforms/FormDocument.C
src/frontends/xforms/FormDocument.h
src/frontends/xforms/FormPreferences.C
src/frontends/xforms/FormPreferences.h
src/frontends/xforms/Makefile.am
src/frontends/xforms/Toolbar_pimpl.C
src/frontends/xforms/Toolbar_pimpl.h
src/frontends/xforms/XFormsView.C
src/frontends/xforms/XMiniBuffer.C
src/frontends/xforms/XMiniBuffer.h
src/frontends/xforms/combox.C [deleted file]
src/frontends/xforms/combox.c [new file with mode: 0644]
src/frontends/xforms/combox.h
src/frontends/xforms/forms/README
src/frontends/xforms/forms/fdfix.sh
src/frontends/xforms/forms/fdfixc.sed
src/frontends/xforms/forms/form_character.fd
src/frontends/xforms/forms/form_document.fd
src/frontends/xforms/forms/form_preferences.fd
src/frontends/xforms/freebrowser.c [new file with mode: 0644]
src/frontends/xforms/freebrowser.h [new file with mode: 0644]
src/frontends/xforms/xforms_helpers.C

index 3d1f8824c0d8c23481f9f9e244bb101ad54ab7b7..07515142a4754a204a84f7a2078031f73b617250 100644 (file)
@@ -2,6 +2,36 @@
 
        * forms/form_character.fd: rearrange widget order.
 
+2003-04-02  Angus Leeming  <leeming@lyx.org>
+
+       * combox.C:
+       * DropDown.[Ch]: removed.
+
+       * combox.[ch]:
+       * freebrowser.[ch]: replace Alejandro's Combox and John's DropDown
+       C++ code with something that can be integrated into xforms itself.
+
+       * Dialogs2.C: remove #include "combox.h".
+
+       * FormCharacter.[Ch]:
+       * forms/form_character.fd:
+       * FormDocument.[Ch]:
+       * forms/form_document.fd:
+       * FormPreferences.[Ch]:
+       * forms/form_preferences.fd:
+       * Toolbar_pimpl.[Ch]: replace code using Alejandro's Combox with
+       code using an FL_OBJECT of type FL_COMBOX.
+
+       * XMiniBuffer.[Ch]: replace John's DropDown with code using
+       FL_FREEBROWSER.
+
+       * Makefile.am: remove combox.C, DropDown.[Ch].
+       Add combox.c, freebrowser.[ch].
+
+       * forms/README:
+       * forms/fdfix.sh:
+       * forms/fdfixc.sed: update to suit the new combox code.
+
 2003-04-02  Angus Leeming  <leeming@lyx.org>
 
        * FormDocument.[Ch]:
index ae61936131da069791adee639d53a2f270ded2d4..0c95fde9811dcf6f1b955914d7438408e52e51ed 100644 (file)
@@ -18,7 +18,6 @@
 
 #include "Tooltips.h"
 #include "xformsBC.h"
-#include "combox.h"
 
 #include "ControlDocument.h"
 #include "FormDocument.h"
diff --git a/src/frontends/xforms/DropDown.C b/src/frontends/xforms/DropDown.C
deleted file mode 100644 (file)
index edbc83a..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/**
- * \file DropDown.C
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author John Levon
- *
- * Full author contact details are available in file CREDITS
- */
-
-#include <config.h>
-
-
-#include "DropDown.h"
-#include "xforms_helpers.h"
-
-#include FORMS_H_LOCATION
-
-#include <iostream>
-#include <cctype>
-
-#ifndef CXX_GLOBAL_CSTD
-using std::isprint;
-#endif
-
-using std::vector;
-
-
-namespace {
-
-extern "C" void C_CompletedCB(FL_OBJECT * ob, long)
-{
-       DropDown * d = static_cast<DropDown*>(ob->u_vdata);
-       d->completed();
-}
-
-
-extern "C" int C_PeekCB(FL_FORM * form, void *xev)
-{
-       DropDown * d = static_cast<DropDown*>(form->u_vdata);
-       return d->peek(static_cast<XEvent*>(xev));
-}
-
-} // namespace anon
-
-
-DropDown::DropDown(FL_OBJECT * ob)
-{
-       form_ = fl_bgn_form(FL_NO_BOX, ob->w, 100);
-       fl_add_box(FL_UP_BOX, 0, 0, ob->w, 100, "");
-       browser_ = fl_add_browser(FL_SELECT_BROWSER, 0, 0, ob->w, 100, "");
-       form_->u_vdata = this;
-       browser_->u_vdata = this;
-       fl_set_object_callback(browser_, C_CompletedCB, 0);
-       fl_register_raw_callback(form_, KeyPressMask|ButtonPressMask, C_PeekCB);
-       fl_end_form();
-}
-
-
-DropDown::~DropDown()
-{
-       if (form_->visible)
-               fl_hide_form(form_);
-       fl_free_form(form_);
-}
-
-
-void DropDown::select(vector<string> const & choices, int x, int y, int w)
-{
-       if (choices.empty())
-               return;
-
-       fl_set_form_geometry(form_, x, y - 100, w, 100);
-       fl_clear_browser(browser_);
-
-       vector<string>::const_iterator cit = choices.begin();
-       vector<string>::const_iterator end = choices.end();
-       for (; cit != end; ++cit) {
-               fl_add_browser_line(browser_, cit->c_str());
-       }
-       fl_select_browser_line(browser_, 1);
-       fl_show_form(form_, FL_PLACE_POSITION, FL_NOBORDER, "");
-       XGrabPointer(fl_get_display(), form_->window, false,
-                    ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
-                    GrabModeAsync, GrabModeAsync, 0, 0, 0);
-       XFlush(fl_get_display());
-}
-
-
-void DropDown::line_up()
-{
-       if (fl_get_browser(browser_) > 1)
-               fl_select_browser_line(browser_, fl_get_browser(browser_) - 1);
-       if (fl_get_browser(browser_) >= fl_get_browser_topline(browser_) +
-           fl_get_browser_screenlines(browser_))
-               fl_set_browser_topline(browser_, fl_get_browser(browser_)
-                                      - fl_get_browser_screenlines(browser_) + 1);
-       if (fl_get_browser(browser_) < fl_get_browser_topline(browser_))
-               fl_set_browser_topline(browser_, fl_get_browser(browser_));
-}
-
-
-void DropDown::line_down()
-{
-       if (fl_get_browser(browser_) < fl_get_browser_maxline(browser_))
-               fl_select_browser_line(browser_, fl_get_browser(browser_) + 1);
-       if (fl_get_browser(browser_) >= fl_get_browser_topline(browser_) +
-           fl_get_browser_screenlines(browser_))
-               fl_set_browser_topline(browser_, fl_get_browser(browser_)
-                                      - fl_get_browser_screenlines(browser_) + 1);
-       if (fl_get_browser(browser_) < fl_get_browser_topline(browser_))
-               fl_set_browser_topline(browser_, fl_get_browser(browser_));
-}
-
-
-int DropDown::peek(XEvent * xev)
-{
-       int x,y;
-       unsigned int keymask;
-
-       fl_get_mouse(&x, &y, &keymask);
-
-       if (xev->type == ButtonPress) {
-               if (!(x >= form_->x && x <= (form_->x + form_->w) &&
-                     y >= form_->y && y << (form_->y + form_->h))) {
-                       fl_hide_form(form_);
-                       return 1;
-               }
-               XUngrabPointer(fl_get_display(), CurrentTime);
-       } else if (xev->type == KeyPress) {
-               char s_r[10]; s_r[9] = '\0';
-               KeySym keysym_return;
-               XLookupString(&xev->xkey, s_r, 10, &keysym_return, 0);
-               switch (keysym_return) {
-               case XK_Down:
-#ifdef XK_KP_Down
-               case XK_KP_Down:
-#endif
-                       line_down();
-                       return 1;
-               case XK_Up:
-#ifdef XK_KP_Up
-               case XK_KP_Up:
-#endif
-                       line_up();
-                       return 1;
-               case XK_Return:
-#ifdef XK_KP_Enter
-               case XK_KP_Enter:
-#endif
-                       completed();
-                       return 1;
-               case XK_Escape:
-                       fl_deselect_browser(browser_);
-                       completed();
-                       return 1;
-               default:
-                       // FIXME: if someone has a got a way to
-                       // convince the event to fall back to the
-                       // minibuffer, I'm glad to hear it.
-                       // fl_XPutBackEvent() doesn't work.
-
-                       // This is a bit less elegant perhaps, but works
-                       // well enough. Angus 11 Jan 2002
-                       if (s_r[0] && isprint(s_r[0])) {
-                               key_pressed(s_r[0]);
-                               return 1;
-                       }
-               }
-       }
-       return 0;
-}
-
-
-void DropDown::completed()
-{
-       XUngrabPointer(fl_get_display(), CurrentTime);
-       fl_hide_form(form_);
-       result(getString(browser_));
-}
-
-
-void DropDown::key_pressed(char c)
-{
-       XUngrabPointer(fl_get_display(), CurrentTime);
-       fl_hide_form(form_);
-       keypress(c);
-}
diff --git a/src/frontends/xforms/DropDown.h b/src/frontends/xforms/DropDown.h
deleted file mode 100644 (file)
index 317301b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// -*- C++ -*-
-/**
- * \file DropDown.h
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author John Levon
- *
- * Full author contact details are available in file CREDITS
- */
-
-#ifndef DROPDOWN_H
-#define DROPDOWN_H
-
-
-#include "forms_fwd.h"
-#include <X11/Xlib.h>
-
-#include <boost/signals/signal1.hpp>
-
-#include "LString.h"
-#include <vector>
-
-class DropDown {
-public:
-       /// constructor
-       DropDown(FL_OBJECT * ob);
-       /// destructor
-       ~DropDown();
-
-       /// choose from the list of choices.
-       void select(std::vector<string> const & choices, int x, int y, int w);
-
-       /// user completed action
-       void completed();
-
-       /// a key was pressed. Act on it.
-       void key_pressed(char c);
-
-       /// signal for completion
-       boost::signal1<void, string const &> result;
-
-       /// signal that a key was pressed
-       boost::signal1<void, char> keypress;
-
-       /// X event
-       int peek(XEvent *);
-
-private:
-       /// move up a browser line
-       void line_up();
-
-       /// move down a browser line
-       void line_down();
-
-       /// our form
-       FL_FORM * form_;
-
-       /// the browser
-       FL_OBJECT * browser_;
-};
-
-#endif // DROPDOWN_H
index d4ba682f1344718ee9452ce14d2827e93eedb5b7..f20ec08aca1ee4120019a17014e40361e025df07 100644 (file)
 #include "FormCharacter.h"
 #include "forms/form_character.h"
 #include "gettext.h"
-#include "combox.h"
 #include "helper_funcs.h"
 #include "xforms_helpers.h"
 #include FORMS_H_LOCATION
+#include "combox.h"
 
 #include "frnt_lang.h"
 
@@ -41,14 +41,6 @@ FormCharacter::FormCharacter(Dialog & parent)
 {}
 
 
-void FormCharacter::ComboInputCB(int, void * v, Combox *)
-{
-       FormCharacter * pre = static_cast<FormCharacter*>(v);
-       // must use input() directly, to avoid treating the Combox
-       // as an FL_OBJECT, leading to a crash (bug 406)
-       pre->bc().input(pre->input(0, 0));
-}
-
 void FormCharacter::build()
 {
        dialog_.reset(build_character(this));
@@ -90,27 +82,9 @@ void FormCharacter::build()
        choice = ' ' + getStringFromVector(getFirst(color), " | ") + ' ';
        fl_addto_choice(dialog_->choice_color, choice.c_str());
 
-       // xforms appears to need this to prevent a crash...
-       fl_addto_choice(dialog_->choice_language, "prevent crash");
-
-       // insert default language box manually
-       fl_addto_form(dialog_->form);
-       FL_OBJECT * ob = dialog_->choice_language;
-       fl_hide_object(dialog_->choice_language);
-
-       combo_language2_.reset(new Combox(FL_COMBOX_DROPLIST));
-       combo_language2_->add(ob->x, ob->y, ob->w, ob->h, 250);
-       combo_language2_->shortcut("#L", 1);
-       combo_language2_->setcallback(ComboInputCB, this);
-       fl_end_form();
-
-       // build up the combox entries
-       vector<LanguagePair>::const_iterator it  = langs.begin();
-       vector<LanguagePair>::const_iterator end = langs.end();
-       for (; it != end; ++it) {
-               combo_language2_->addto(it->first);
-       }
-       combo_language2_->select(1);
+       choice = ' ' + getStringFromVector(getFirst(langs), " | ") + ' ';
+       fl_addto_combox(dialog_->combox_language, choice.c_str());
+       fl_set_combox_browser_height(dialog_->combox_language, 250);
 
        // Manage the ok, apply and cancel/close buttons
        bcview().setApply(dialog_->button_apply);
@@ -141,7 +115,7 @@ void FormCharacter::apply()
        pos = fl_get_choice(dialog_->choice_color);
        controller().setColor(color_[pos - 1]);
 
-       pos = combo_language2_->get();
+       pos = fl_get_combox(dialog_->combox_language);
        controller().setLanguage(lang_[pos - 1]);
 
        bool const toggleall = fl_get_button(dialog_->check_toggle_all);
@@ -170,7 +144,7 @@ void FormCharacter::update()
        fl_set_choice(dialog_->choice_color, pos+1);
 
        pos = int(findPos(lang_, controller().getLanguage()));
-       combo_language2_->select(pos+1);
+       fl_set_combox(dialog_->combox_language, pos+1);
 
        fl_set_button(dialog_->check_toggle_all, controller().getToggleAll());
 }
@@ -204,7 +178,7 @@ ButtonPolicy::SMInput FormCharacter::input(FL_OBJECT *, long)
        if (color_[pos - 1] != LColor::ignore)
                activate = ButtonPolicy::SMI_VALID;
 
-       pos = combo_language2_->get();
+       pos = fl_get_combox(dialog_->combox_language);
        if (lang_[pos - 1] != "No change")
                activate = ButtonPolicy::SMI_VALID;
 
index 42e987bb7b65cdb769e684e9767e02b1e5cbadb9..c70c0b7c1b9adb87a5a98bd5b6fde70624f7036f 100644 (file)
@@ -20,9 +20,6 @@
 #include "LColor.h"           // for LColor enum
 #include "character.h"        // for FONT_STATE enum
 
-#include <boost/scoped_ptr.hpp>
-
-class Combox;
 struct FD_character;
 
 /**
@@ -49,12 +46,6 @@ private:
        /// Filter the inputs on callback from xforms
        virtual ButtonPolicy::SMInput input(FL_OBJECT *, long);
 
-       /** Callback method (used only to activate Apply button when
-           combox is changed */
-       static void ComboInputCB(int, void *, Combox *);
-
-       ///
-       boost::scoped_ptr<Combox> combo_language2_;
        ///
        std::vector<LyXFont::FONT_FAMILY>  family_;
        ///
index fd9c18ff3b86d37843eb8020bd14daaec32d066f..3a6057fb14293e8491d45389ac7abeff1c96cd12 100644 (file)
@@ -20,7 +20,6 @@
 
 #include "bmtable.h"
 #include "checkedwidgets.h"
-#include "combox.h"
 #include "input_validators.h" // fl_unsigned_float_filter
 #include "xforms_helpers.h"
 
@@ -39,6 +38,7 @@
 
 #include XPM_H_LOCATION
 #include FORMS_H_LOCATION
+#include "combox.h"
 
 #include <boost/bind.hpp>
 
@@ -88,6 +88,7 @@ void FormDocument::build()
        class_.reset(build_document_class(this));
 
        // disable for read-only documents
+       bcview().addReadOnly(class_->combox_doc_class);
        bcview().addReadOnly(class_->radio_doc_indent);
        bcview().addReadOnly(class_->radio_doc_skip);
        bcview().addReadOnly(class_->choice_doc_pagestyle);
@@ -118,19 +119,14 @@ void FormDocument::build()
 
        FL_OBJECT * obj;
 
-       // the class list is a combo-box and has to be inserted manually
-       obj = class_->choice_doc_class;
-       fl_deactivate_object(obj);
-       fl_addto_form(class_->form);
-       combo_doc_class.reset(new Combox(FL_COMBOX_DROPLIST));
-       combo_doc_class->add(obj->x, obj->y, obj->w, obj->h, 400);
-       combo_doc_class->shortcut("#C",1);
-       combo_doc_class->setcallback(ComboInputCB, this);
-       fl_end_form();
-       for (LyXTextClassList::const_iterator cit = textclasslist.begin();
-            cit != textclasslist.end(); ++cit) {
-               combo_doc_class->addto(cit->description());
+       // Fill the combox and choices.
+       obj = class_->combox_doc_class;
+       LyXTextClassList::const_iterator tit  = textclasslist.begin();
+       LyXTextClassList::const_iterator tend = textclasslist.end();
+       for (; tit != tend; ++tit) {
+               fl_addto_combox(obj, tit->description().c_str());
        }
+       fl_set_combox_browser_height(obj, 400);
 
        fl_addto_choice(class_->choice_doc_spacing,
                        _(" Single | OneHalf | Double | Custom "));
@@ -239,6 +235,7 @@ void FormDocument::build()
        language_.reset(build_document_language(this));
 
        // disable for read-only documents
+       bcview().addReadOnly(language_->combox_language);
        bcview().addReadOnly(language_->choice_inputenc);
        bcview().addReadOnly(language_->choice_quotes_language);
        bcview().addReadOnly(language_->radio_single);
@@ -252,22 +249,13 @@ void FormDocument::build()
        // Store the identifiers for later
        lang_ = getSecond(langs);
 
-       // The language is a combo-box and has to be inserted manually
-       obj = language_->choice_language;
-       fl_deactivate_object(obj);
-       fl_addto_form(language_->form);
-       combo_language.reset(new Combox(FL_COMBOX_DROPLIST));
-       combo_language->add(obj->x, obj->y, obj->w, obj->h, 400);
-       combo_language->shortcut("#L",1);
-       combo_language->setcallback(ComboInputCB, this);
-       fl_end_form();
-
        vector<frnt::LanguagePair>::const_iterator lit  = langs.begin();
        vector<frnt::LanguagePair>::const_iterator lend = langs.end();
        for (; lit != lend; ++lit) {
-               combo_language->addto(lit->first);
+               fl_addto_combox(language_->combox_language,
+                               lit->first.c_str());
        }
-       combo_language->select(1);
+       fl_set_combox_browser_height(language_->combox_language, 400);
 
        fl_addto_choice(language_->choice_quotes_language,
                        _(" ``text'' | ''text'' | ,,text`` | ,,text'' |"
@@ -416,6 +404,8 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
                setEnabled(class_->input_doc_spacing,
                           fl_get_choice(class_->choice_doc_spacing) == 4);
 
+       } else if (ob == class_->combox_doc_class) {
+               CheckChoiceClass();
        } else if (ob == class_->radio_doc_skip ||
                   ob == class_->radio_doc_indent ||
                   ob == class_->choice_doc_skip) {
@@ -449,7 +439,7 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
 
        } else if (ob == dialog_->button_reset_defaults) {
                BufferParams & params = controller().params();
-               params.textclass = combo_doc_class->get() - 1;
+               params.textclass = fl_get_combox(class_->combox_doc_class) - 1;
                params.useClassDefaults();
                UpdateLayoutDocument(params);
 
@@ -593,15 +583,6 @@ ButtonPolicy::SMInput FormDocument::input(FL_OBJECT * ob, long)
 }
 
 
-void FormDocument::ComboInputCB(int, void * v, Combox * combox)
-{
-       FormDocument * pre = static_cast<FormDocument*>(v);
-       if (combox == pre->combo_doc_class.get())
-               pre->CheckChoiceClass();
-       pre->bc().valid();
-}
-
-
 bool FormDocument::class_apply(BufferParams &params)
 {
        bool redo = false;
@@ -616,7 +597,7 @@ bool FormDocument::class_apply(BufferParams &params)
        params.fontsize = getString(class_->choice_doc_fontsize);
        params.pagestyle = getString(class_->choice_doc_pagestyle);
 
-       params.textclass = combo_doc_class->get() - 1;
+       params.textclass = fl_get_combox(class_->combox_doc_class) - 1;
 
        BufferParams::PARSEP tmpsep = params.paragraph_separation;
        if (fl_get_button(class_->radio_doc_indent))
@@ -778,7 +759,7 @@ bool FormDocument::language_apply(BufferParams & params)
        else
                params.quotes_times = InsetQuotes::DoubleQ;
 
-       int const pos = combo_language->get();
+       int const pos = fl_get_combox(language_->combox_language);
        Language const * new_language = languages.getLanguage(lang_[pos-1]);
        if (!new_language)
                new_language = default_language;
@@ -820,11 +801,9 @@ void FormDocument::bullets_apply(BufferParams & params)
        /* update the bullet settings */
        BufferParams & buf_params = controller().params();
 
-       // a little bit of loop unrolling
-       params.user_defined_bullets[0] = buf_params.temp_bullets[0];
-       params.user_defined_bullets[1] = buf_params.temp_bullets[1];
-       params.user_defined_bullets[2] = buf_params.temp_bullets[2];
-       params.user_defined_bullets[3] = buf_params.temp_bullets[3];
+       for (int i = 0; i < 4; ++i) {
+               params.user_defined_bullets[i] = buf_params.temp_bullets[i];
+       }
 }
 
 
@@ -835,7 +814,7 @@ void FormDocument::UpdateClassParams(BufferParams const & params)
 
        LyXTextClass const & tclass = textclasslist[params.textclass];
 
-       combo_doc_class->select(tclass.description());
+       fl_set_combox(class_->combox_doc_class, params.textclass + 1);
        fl_clear_choice(class_->choice_doc_fontsize);
        fl_addto_choice(class_->choice_doc_fontsize, "default");
        fl_addto_choice(class_->choice_doc_fontsize,
@@ -945,7 +924,7 @@ void FormDocument::language_update(BufferParams const & params)
                return;
 
        int const pos = int(findPos(lang_, params.language->lang()));
-       combo_language->select(pos+1);
+       fl_set_combox(language_->combox_language, pos+1);
 
        fl_set_choice_text(language_->choice_inputenc, params.inputenc.c_str());
        fl_set_choice(language_->choice_quotes_language, params.quotes_language + 1);
@@ -1095,13 +1074,9 @@ void FormDocument::bullets_update(BufferParams const & params)
 void FormDocument::checkReadOnly()
 {
        if (bc().readOnly(controller().bufferIsReadonly())) {
-               combo_doc_class->deactivate();
-               combo_language->deactivate();
                postWarning(_("Document is read-only."
                              " No changes to layout permitted."));
        } else {
-               combo_doc_class->activate();
-               combo_language->activate();
                clearMessage();
        }
 }
@@ -1238,7 +1213,8 @@ void FormDocument::CheckChoiceClass()
 {
        BufferParams & params = controller().params();
 
-       lyx::textclass_type const tc = combo_doc_class->get() - 1;
+       lyx::textclass_type const tc =
+               fl_get_combox(class_->combox_doc_class) - 1;
 
        if (controller().loadTextclass(tc)) {
                params.textclass = tc;
@@ -1254,7 +1230,7 @@ void FormDocument::CheckChoiceClass()
 
        } else {
                int const revert = int(params.textclass);
-               combo_doc_class->select(revert + 1);
+               fl_set_combox(class_->combox_doc_class, revert + 1);
        }
 }
 
index ad3a5a34065f6a7af3a303a22dd624522410d6ea..41d5686e2435145f1aa2b37181e4582279c14d2c 100644 (file)
@@ -21,7 +21,6 @@
 
 class ControlDocument;
 
-class Combox;
 class BufferParams;
 
 struct FD_document;
@@ -37,8 +36,6 @@ struct FD_document_bullet;
 class FormDocument : public FormCB<ControlDocument, FormDB<FD_document> > {
 public:
        FormDocument();
-       ///
-       static void ComboInputCB(int, void *, Combox *);
 private:
        /** Redraw the form (on receipt of a Signal indicating, for example,
            that the xforms colours have been re-mapped). */
@@ -114,10 +111,6 @@ private:
        ///
        FL_OBJECT * fbullet;
        ///
-       boost::scoped_ptr<Combox> combo_language;
-       ///
-       boost::scoped_ptr<Combox> combo_doc_class;
-       ///
        std::vector<string> lang_;
 };
 
index 7b2634586e00068d4d8c471ae89442d35fb1e8f0..967d2acd6017ceda3fae028c89db0ba5dda0e163 100644 (file)
@@ -17,7 +17,6 @@
 #include "xformsBC.h"
 #include "ButtonController.h"
 
-#include "combox.h"
 #include "Color.h"
 #include "input_validators.h"
 #include "forms_gettext.h"
@@ -48,6 +47,8 @@
 #include <boost/bind.hpp>
 
 #include FORMS_H_LOCATION
+#include "combox.h"
+
 #include <utility>
 #include <iomanip>
 #include <X11/Xlib.h>
@@ -1603,7 +1604,7 @@ FD_preferences_language const * FormPreferences::Language::dialog()
 
 void FormPreferences::Language::apply(LyXRC & rc)
 {
-       int const pos = combo_default_lang->get();
+       int const pos = fl_get_combox(dialog_->combox_default_lang);
        rc.default_language = lang_[pos-1];
 
        int button = fl_get_button(dialog_->check_use_kbmap);
@@ -1657,38 +1658,18 @@ void FormPreferences::Language::build()
        vector<frnt::LanguagePair> const langs = frnt::getLanguageData(false);
        lang_ = getSecond(langs);
 
-       // The default_language is a combo-box and has to be inserted manually
-       fl_freeze_form(dialog_->form);
-       fl_addto_form(dialog_->form);
-
-       FL_OBJECT * obj = dialog_->choice_default_lang;
-       fl_deactivate_object(dialog_->choice_default_lang);
-       combo_default_lang.reset(new Combox(FL_COMBOX_DROPLIST));
-       combo_default_lang->add(obj->x, obj->y, obj->w, obj->h, 400);
-       combo_default_lang->shortcut("#L",1);
-       combo_default_lang->setcallback(ComboCB, &parent_);
-
+       FL_OBJECT * obj = dialog_->combox_default_lang;
        vector<frnt::LanguagePair>::const_iterator lit  = langs.begin();
        vector<frnt::LanguagePair>::const_iterator lend = langs.end();
        for (; lit != lend; ++lit) {
-               combo_default_lang->addto(lit->first);
+               fl_addto_combox(obj, lit->first.c_str());
        }
-       combo_default_lang->select(1);
-
-       fl_end_form();
-       fl_unfreeze_form(dialog_->form);
+       fl_set_combox_browser_height(obj, 400);
 
        // set up the feedback mechanism
        setPrehandler(dialog_->input_package);
        setPrehandler(dialog_->check_use_kbmap);
-
-       // This is safe, as nothing is done to the pointer, other than
-       // to use its address in a block-if statement.
-       // No it's not! Leads to crash.
-       // setPrehandler(
-       //              reinterpret_cast<FL_OBJECT *>(combo_default_lang),
-       //              C_FormPreferencesFeedbackCB);
-
+       setPrehandler(dialog_->combox_default_lang);
        setPrehandler(dialog_->input_kbmap1);
        setPrehandler(dialog_->input_kbmap2);
        setPrehandler(dialog_->check_rtl_support);
@@ -1709,7 +1690,7 @@ void FormPreferences::Language::build()
 string const
 FormPreferences::Language::feedback(FL_OBJECT const * const ob) const
 {
-       if (reinterpret_cast<Combox const *>(ob) == combo_default_lang.get())
+       if (ob == dialog_->combox_default_lang)
                return LyXRC::getDescription(LyXRC::RC_DEFAULT_LANGUAGE);
        if (ob == dialog_->check_use_kbmap)
                return LyXRC::getDescription(LyXRC::RC_KBMAP);
@@ -1776,7 +1757,7 @@ void FormPreferences::Language::update(LyXRC const & rc)
                      rc.use_kbmap);
 
        int const pos = int(findPos(lang_, rc.default_language));
-       combo_default_lang->select(pos + 1);
+       fl_set_combox(dialog_->combox_default_lang, pos + 1);
 
        if (rc.use_kbmap) {
                fl_set_input(dialog_->input_kbmap1,
@@ -1810,15 +1791,6 @@ void FormPreferences::Language::update(LyXRC const & rc)
 }
 
 
-void FormPreferences::Language::ComboCB(int, void * v, Combox * combox)
-{
-       FormPreferences * pre = static_cast<FormPreferences*>(v);
-       // This is safe, as nothing is done to the pointer, other than
-       // to use its address in a block-if statement.
-       pre->bc().valid(pre->input(reinterpret_cast<FL_OBJECT *>(combox), 0));
-}
-
-
 FormPreferences::LnFmisc::LnFmisc(FormPreferences &  p)
        : parent_(p)
 {}
index bcf55de2526874edefdd3dd7538ce0752b538005..9ef2f6adfb27806d8151d8ebdc2388dc1e0a156e 100644 (file)
@@ -26,7 +26,6 @@
 
 class ControlPrefs;
 
-class Combox;
 class Dialogs;
 class LyXView;
 class RGBColor;
@@ -291,8 +290,6 @@ private:
                bool input(FL_OBJECT const * const);
                ///
                void update(LyXRC const & rc);
-               ///
-               static void ComboCB(int, void *, Combox *);
 
        private:
                ///
@@ -300,8 +297,6 @@ private:
                ///
                boost::scoped_ptr<FD_preferences_language> dialog_;
                ///
-               boost::scoped_ptr<Combox> combo_default_lang;
-               ///
                std::vector<string> lang_;
        };
        ///
index 980495d15a6d9261dadc78492c9630ed99b10588..ee69d247e7f25724eb43f2712dcd54d667d686c5 100644 (file)
@@ -18,8 +18,10 @@ libxforms_la_SOURCES = \
        bmtable.h \
        checkedwidgets.C \
        checkedwidgets.h \
-       combox.C \
+       combox.c \
        combox.h \
+       freebrowser.c \
+       freebrowser.h \
        fdesign_base.C \
        fdesign_base.h \
        input_validators.C \
@@ -48,8 +50,6 @@ libxforms_la_SOURCES = \
        ColorHandler.h \
        Dialogs.C \
        Dialogs2.C \
-       DropDown.h \
-       DropDown.C \
        FileDialog.C \
        FontInfo.C \
        FontInfo.h \
index 9e8a2cf6d20b62f6741002952093c8eb698c0abe..e5b38575de54635c81a17c0b1a32aeeb7468519d 100644 (file)
@@ -26,6 +26,8 @@
 #include "Tooltips.h"
 #include FORMS_H_LOCATION
 #include "combox.h"
+#include "xforms_helpers.h"
+
 #include "ToolbarDefaults.h"
 #include "LyXAction.h"
 
@@ -84,9 +86,8 @@ Toolbar::Pimpl::toolbarItem::operator=(toolbarItem const & ti)
 
 
 Toolbar::Pimpl::Pimpl(LyXView * o, int x, int y)
-       : owner_(static_cast<XFormsView *>(o)), xpos(x), ypos(y)
+       : owner_(static_cast<XFormsView *>(o)), combox_(0), xpos(x), ypos(y)
 {
-       combox_ = 0;
        tooltip_ = new Tooltips();
 }
 
@@ -99,8 +100,6 @@ Toolbar::Pimpl::~Pimpl()
        //toollist.clear();
        toollist_.erase(toollist_.begin(), toollist_.end());
 
-       delete combox_;
-
        fl_unfreeze_form(owner_->getForm());
        delete tooltip_;
 }
@@ -112,10 +111,10 @@ void Toolbar::Pimpl::update()
        ToolbarList::const_iterator end = toollist_.end();
        for (; p != end; ++p) {
                if (p->action == ToolbarDefaults::LAYOUTS && combox_) {
-                       if (owner_->getLyXFunc().getStatus(LFUN_LAYOUT).disabled())
-                               combox_->deactivate();
-                       else
-                               combox_->activate();
+                       LyXFunc const & lf = owner_->getLyXFunc();
+                       bool const disable =
+                               lf.getStatus(LFUN_LAYOUT).disabled();
+                       setEnabled(combox_, !disable);
                        continue;
                }
 
@@ -147,16 +146,25 @@ void Toolbar::Pimpl::update()
 }
 
 
-// this one is not "C" because combox callbacks are really C++ %-|
-void Toolbar::Pimpl::layoutSelectedCB(int, void * arg, Combox *)
+namespace {
+
+void C_layoutSelectedCB(FL_OBJECT * ob, long)
 {
-       reinterpret_cast<Toolbar::Pimpl *>(arg)->layoutSelected();
+       if (!ob || !ob->u_vdata)
+               return;
+       Toolbar::Pimpl * ptr = static_cast<Toolbar::Pimpl *>(ob->u_vdata);
+       ptr->layoutSelected();
 }
 
+} // namespace anon
+
 
 void Toolbar::Pimpl::layoutSelected()
 {
-       string const & layoutguiname = combox_->getline();
+       if (!combox_)
+               return;
+
+       string const & layoutguiname = getString(combox_);
        LyXTextClass const & tc =
                owner_->buffer()->params.getLyXTextClass();
 
@@ -175,50 +183,64 @@ void Toolbar::Pimpl::layoutSelected()
 
 void Toolbar::Pimpl::setLayout(string const & layout)
 {
-       if (combox_) {
-               LyXTextClass const & tc =
-                       owner_->buffer()->params.getLyXTextClass();
-               combox_->select(_(tc[layout]->name()));
+       if (!combox_)
+               return;
+
+       LyXTextClass const & tc = owner_->buffer()->params.getLyXTextClass();
+       string const layoutname = _(tc[layout]->name());
+
+       int const nnames = fl_get_combox_maxitems(combox_);
+       for (int i = 1; i <= nnames; ++i) {
+               string const name = fl_get_combox_line(combox_, i);
+               if (name == layoutname) {
+                       fl_set_combox(combox_, i);
+                       break;
+               }
        }
 }
 
 
 void Toolbar::Pimpl::updateLayoutList(bool force)
 {
-       // Update the layout display
-       if (!combox_) return;
+       if (!combox_)
+               return;
 
        // If textclass is different, we need to update the list
-       if (combox_->empty() || force) {
-               combox_->clear();
+       if (fl_get_combox_maxitems(combox_) == 0 || force) {
+               fl_clear_combox(combox_);
                LyXTextClass const & tc =
                        owner_->buffer()->params.getLyXTextClass();
                LyXTextClass::const_iterator end = tc.end();
                for (LyXTextClass::const_iterator cit = tc.begin();
                     cit != end; ++cit) {
                        // ignore obsolete entries
-                       if ((*cit)->obsoleted_by().empty())
-                               combox_->addline(_((*cit)->name()));
+                       if ((*cit)->obsoleted_by().empty()) {
+                               string const & name = _((*cit)->name());
+                               fl_addto_combox(combox_, name.c_str());
+                       }
                }
        }
        // we need to do this.
-       combox_->redraw();
+       fl_redraw_object(combox_);
 }
 
 
 void Toolbar::Pimpl::clearLayoutList()
 {
-       if (combox_) {
-               combox_->clear();
-               combox_->redraw();
-       }
+       if (!combox_)
+               return;
+
+       fl_clear_combox(combox_);
+       fl_redraw_object(combox_);
 }
 
 
 void Toolbar::Pimpl::openLayoutList()
 {
-       if (combox_)
-               combox_->show();
+       if (!combox_)
+               return;
+
+       fl_show_combox_browser(combox_);
 }
 
 
@@ -281,8 +303,6 @@ void setPixmap(FL_OBJECT * obj, int action)
 
 void Toolbar::Pimpl::add(int action)
 {
-       FL_OBJECT * obj;
-
        toolbarItem item;
        item.action = action;
 
@@ -295,15 +315,24 @@ void Toolbar::Pimpl::add(int action)
                break;
        case ToolbarDefaults::LAYOUTS:
                xpos += standardspacing;
-               if (!combox_)
-                       combox_ = new Combox(FL_COMBOX_DROPLIST);
-               combox_->add(xpos, ypos, 135, height, 400);
-               combox_->setcallback(layoutSelectedCB, this);
-               combox_->resize(FL_RESIZE_ALL);
-               combox_->gravity(NorthWestGravity, NorthWestGravity);
+               if (combox_)
+                       break;
+
+               combox_ = fl_add_combox(FL_DROPLIST_COMBOX,
+                                       xpos, ypos, 135, height, "");
+               fl_set_combox_browser_height(combox_, 400);
+               fl_set_object_boxtype(combox_, FL_DOWN_BOX);
+               fl_set_object_color(combox_, FL_MCOL, FL_MCOL);
+               fl_set_object_gravity(combox_, FL_NorthWest, FL_NorthWest);
+               fl_set_object_resize(combox_, FL_RESIZE_ALL);
+
+               combox_->u_vdata = this;
+               fl_set_object_callback(combox_, C_layoutSelectedCB, 0);
                xpos += 135;
                break;
-       default:
+       default: {
+               FL_OBJECT * obj;
+
                xpos += standardspacing;
                item.icon = obj =
                        fl_add_pixmapbutton(FL_NORMAL_BUTTON,
@@ -336,6 +365,7 @@ void Toolbar::Pimpl::add(int action)
                 */
                break;
        }
+       }
 
        toollist_.push_back(item);
 }
index 982646c603e27338fe2d516518238be87b5ff1c3..26db1ca67157d6f18ce281e97b28c30d55d75ac0 100644 (file)
 
 class XFormsView;
 class Tooltips;
-class Combox;
 
 /** The LyX xforms toolbar class
  */
 struct Toolbar::Pimpl {
 public:
-       /// called when user selects a layout from combox
-       static void layoutSelectedCB(int, void *, Combox *);
-
        /// create an empty toolbar
        Pimpl(LyXView * o, int x, int y);
 
@@ -49,7 +45,7 @@ public:
        void openLayoutList();
        /// Erase the layout list
        void clearLayoutList();
-       /// the non-static version of layoutSelectedCB
+       ///
        void layoutSelected();
 
        /// an item on the toolbar
@@ -79,7 +75,7 @@ public:
        /// tooltips manager
        Tooltips * tooltip_;
        /// layout combo
-       Combox * combox_;
+       FL_OBJECT * combox_;
        /// x position of end of toolbar
        int xpos;
        /// y position of end of toolbar
index 555b01f268c44c08be66b8b16b421e6601f7b7eb..c93f9d32a3f97b42d1b1fba341e31195b6c29f79 100644 (file)
@@ -173,8 +173,6 @@ void XFormsView::create_form_form_main(int width, int height)
        fl_set_form_minsize(getForm(), 50, 50);
 
        fl_end_form();
-
-       minibuffer_->dd_init();
 }
 
 
index e032ccc8ef31aca470295924af4f36936b9eb897..5a8b85bb93a84dc748412aa540f69993f51b5724 100644 (file)
 #include <config.h>
 
 #include "XMiniBuffer.h"
-#include "DropDown.h"
 #include "ControlCommandBuffer.h"
+#include "freebrowser.h"
+#include "xforms_helpers.h"
 
 #include "gettext.h"
 
 #include "frontends/Timeout.h"
 
+#include "support/lstrings.h"
+
 #include <boost/bind.hpp>
 
 #include <vector>
@@ -38,6 +41,10 @@ namespace {
 FL_OBJECT * create_input_box(void * parent, int type,
                             FL_Coord, FL_Coord, FL_Coord, FL_Coord);
 
+FL_FREEBROWSER * create_freebrowser(void * parent);
+
+FL_OBJECT * get_freebrowser_browser(boost::shared_ptr<FL_FREEBROWSER> &);
+
 } // namespace anon
 
 
@@ -47,6 +54,8 @@ XMiniBuffer::XMiniBuffer(ControlCommandBuffer & control,
          info_shown_(false)
 {
        input_ = create_input_box(this, FL_NORMAL_INPUT, x, y, h, w);
+       freebrowser_.reset(create_freebrowser(this), fl_free_freebrowser);
+       
        info_timer_.reset(new Timeout(1500));
        idle_timer_.reset(new Timeout(6000));
        info_con = info_timer_->timeout.connect(boost::bind(&XMiniBuffer::info_timeout, this));
@@ -61,12 +70,34 @@ XMiniBuffer::~XMiniBuffer()
 {}
 
 
-// thanks for nothing, xforms (recursive creation not allowed)
-void XMiniBuffer::dd_init()
+void XMiniBuffer::freebrowserCB(int action)
 {
-       dropdown_.reset(new DropDown(input_));
-       result_con = dropdown_->result.connect(boost::bind(&XMiniBuffer::set_complete_input, this, _1));
-       keypress_con = dropdown_->keypress.connect(boost::bind(&XMiniBuffer::append_char, this, _1));
+       if (action < 0 || action > 1)
+               // unrecognized action
+               return;
+
+       if (action == 0)
+               // The freebrowser has been hidden
+               return;
+
+       if (freebrowser_->last_printable) {
+               // Append this char to the current input contents
+               string input = getString(input_);
+               input += freebrowser_->last_printable;
+               fl_set_input(input_, input.c_str());
+
+       } else {
+               // Fill the input widget with the selected
+               // browser entry.
+               FL_OBJECT * browser = get_freebrowser_browser(freebrowser_);
+               string const str = getString(browser);
+
+               if (!str.empty()) {
+                       // add a space so the user can type
+                       // an argument immediately
+                       set_input(str + ' ');
+               }
+       }
 }
 
 
@@ -139,6 +170,19 @@ int XMiniBuffer::peek_event(FL_OBJECT * ob, int event,
 
                        set_input(new_input);
 
+                       // Fill freebrowser_'s browser with the list of
+                       // available completions
+                       FL_OBJECT * browser =
+                               get_freebrowser_browser(freebrowser_);
+                       fl_clear_browser(browser);
+                       vector<string>::const_iterator cit = comp.begin();
+                       vector<string>::const_iterator end = comp.end();
+                       for (; cit != end; ++cit) {
+                               fl_add_browser_line(browser, cit->c_str());
+                       }
+                       fl_select_browser_line(browser, 1);
+
+                       // Set the position of the freebrowser and display it.
                        int x,y,w,h;
                        fl_get_wingeometry(fl_get_real_object_window(input_),
                                           &x, &y, &w, &h);
@@ -148,7 +192,9 @@ int XMiniBuffer::peek_event(FL_OBJECT * ob, int event,
                        x += air;
                        y += h - (input_->h + air);
                        w = input_->w;
-                       dropdown_->select(comp, x, y, w);
+                       h = 100;
+
+                       fl_show_freebrowser(freebrowser_.get(), x, y-h, w, h);
                        return 1;
                }
                case 27:
@@ -242,30 +288,6 @@ void XMiniBuffer::redraw()
 }
 
 
-void XMiniBuffer::append_char(char c)
-{
-       if (!c || !isprint(c))
-               return;
-
-       char const * tmp = fl_get_input(input_);
-       string str = tmp ? tmp : "";
-
-       str += c;
-
-       fl_set_input(input_, str.c_str());
-}
-
-
-void XMiniBuffer::set_complete_input(string const & str)
-{
-       if (!str.empty()) {
-               // add a space so the user can type
-               // an argument immediately
-               set_input(str + ' ');
-       }
-}
-
-
 void XMiniBuffer::message(string const & str)
 {
        if (!isEditingMode())
@@ -291,6 +313,17 @@ int C_XMiniBuffer_peek_event(FL_OBJECT * ob, int event,
 }
 
 
+extern "C"
+void C_freebrowserCB(FL_FREEBROWSER * fb, int action)
+{
+       if (!fb || !fb->parent)
+               return;
+
+       XMiniBuffer * ptr = static_cast<XMiniBuffer *>(fb->parent);
+       ptr->freebrowserCB(action);
+}
+
+
 FL_OBJECT * create_input_box(void * parent, int type,
                             FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h)
 {
@@ -309,4 +342,19 @@ FL_OBJECT * create_input_box(void * parent, int type,
        return obj;
 }
 
+
+FL_FREEBROWSER * create_freebrowser(void * parent)
+{
+       FL_FREEBROWSER * fb = fl_create_freebrowser(parent);
+       fb->want_printable = 1;
+       fb->callback = C_freebrowserCB;
+       return fb;
+}
+
+FL_OBJECT * get_freebrowser_browser(boost::shared_ptr<FL_FREEBROWSER> & fb)
+{
+       FL_FREEBROWSER * ptr = fb.get();
+       return ptr ? fl_get_freebrowser_browser(ptr) : 0;
+}
+
 } // namespace anon
index 3785aebaa133cee3d835ad072e6ab7c207ee22c0..d81472ef7d74464bfebe269c5dce8ae3c1ae7306 100644 (file)
 
 #include "LString.h"
 #include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
 #include <boost/signals/connection.hpp>
 
-class DropDown;
+struct fl_freebrowser_;
+typedef fl_freebrowser_ FL_FREEBROWSER;
+
 class ControlCommandBuffer;
 class Timeout;
 
@@ -34,9 +37,6 @@ public:
        ///
        ~XMiniBuffer();
 
-       /// create drop down
-       void dd_init();
-
        /// repaint the minibuffer
        void redraw();
 
@@ -52,6 +52,9 @@ public:
        /// disable event management
        void freeze();
 
+       /// xforms callback routine
+       void freebrowserCB(int action);
+
 private:
        /// Are we in editing mode?
        bool isEditingMode() const;
@@ -62,15 +65,6 @@ private:
        /// go back to "at rest" message
        void idle_timeout();
 
-       /**
-        * Append "c" to the current input contents when the completion
-        * list is displayed and has focus.
-        */
-       void append_char(char c);
-
-       /// completion selection callback
-       void set_complete_input(string const & str);
-
        /// set the minibuffer content in editing mode
        void set_input(string const &);
 
@@ -81,7 +75,7 @@ private:
        void show_info(string const & info, string const & input, bool append = true);
 
        /// the dropdown menu
-       boost::scoped_ptr<DropDown> dropdown_;
+       boost::shared_ptr<FL_FREEBROWSER> freebrowser_;
 
        /// info timer
        boost::scoped_ptr<Timeout> info_timer_;
diff --git a/src/frontends/xforms/combox.C b/src/frontends/xforms/combox.C
deleted file mode 100644 (file)
index 00f27bc..0000000
+++ /dev/null
@@ -1,556 +0,0 @@
-/**
- * \file combox.C
- * Copyright 1996Alejandro Aguilar Sierra
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
- *
- * \author Alejandro Aguilar Sierra
- *
- * Full author contact details are available in file CREDITS
- */
-
-/* A combination of two objects (a button and a browser) is encapsulated to
- * get a combobox-like object. All XForms functions are hidden.
- *
- */
-
-/* Change log:
- *
- *  2/06/1996,   Alejandro Aguilar Sierra
- *    Created and tested.
- *
- *  4/06/1996,   Alejandro Aguilar Sierra
- *    Added droplist mode (a button with a black down arrow at right)
- *    and support for middle and right buttons, as XForms choice object.
- *
- *  6/06/1996,   Lars Gullik Bjønnes
- *    Added a combox with an input object. and a pre and a post handle.
- *
- *  22/07/96,    Alejandro Aguilar Sierra
- *    Assigned to the browser its own popup window. No more need of
- *    external pre and post handlers to simulate the wanted behaviour.
- *
- */
-
-#include <config.h>
-
-
-#include "combox.h"
-//#include <cstring>
-
-#include "debug.h"
-
-using std::endl;
-
-// These are C wrappers around static members of Combox, used as
-// callbacks for xforms.
-extern "C" {
-
-       static
-       void C_Combox_input_cb(FL_OBJECT * ob, long data)
-       {
-               Combox::input_cb(ob, data);
-       }
-
-       static
-       void C_Combox_combo_cb(FL_OBJECT * ob, long data)
-       {
-               Combox::combo_cb(ob, data);
-       }
-
-       static
-       int C_Combox_peek_event(FL_FORM * form, void *xev)
-       {
-               return Combox::peek_event(form, xev);
-       }
-
-}
-
-
-Combox::Combox(combox_type t)
-       : type(t)
-{
-   browser = button = 0;
-   callback = 0;
-   label = 0;
-   cb_arg = 0;
-   _pre = 0;
-   _post = 0;
-   sel = 0;
-   form = 0;
-}
-
-
-Combox::~Combox()
-{
-       // This is now handled by the XFormsView destructor (Lgb)
-       // remove();
-}
-
-
-void Combox::clear()
-{
-       if (browser) fl_clear_browser(browser);
-       sel = 0;
-       if (type == FL_COMBOX_INPUT)
-               fl_set_input(label, "");
-       else
-               fl_set_object_label(label, "");
-       is_empty = true;
-}
-
-
-void Combox::remove()
-{
-       lyxerr[Debug::GUI] << "Button: " << button << endl;
-       if (button) {
-               fl_delete_object(button);
-               fl_free_object(button);
-       }
-
-       lyxerr[Debug::GUI] << "Label: " << label << endl;
-       if (label && label != button) {
-               fl_delete_object(label);
-               fl_free_object(label);
-       }
-
-       lyxerr[Debug::GUI] << "Form: " << form << endl;
-       lyxerr[Debug::GUI] << "Browser: " << browser << endl;
-       if (form && browser) {
-          fl_delete_object(browser);
-          fl_free_object(browser);
-          fl_free_form(form);
-       }
-       button = 0;
-       browser = 0;
-       label = 0;
-       form = 0;
-       sel = 0;
-       is_empty = true;
-}
-
-
-void Combox::addline(string const & text)
-{
-       if (!browser) return;
-       fl_add_browser_line(browser, text.c_str());
-
-       // By default the first item is selected
-       if (!sel) {
-               sel = 1;
-               if (type == FL_COMBOX_INPUT)
-                       fl_set_input(label, text.c_str());
-               else
-                       fl_set_object_label(label, text.c_str());
-       }
-       is_empty = false;
-}
-
-
-bool Combox::select(string const & t)
-{
-       if (!browser || t.empty()) return false;
-       int const maxline = fl_get_browser_maxline(browser);
-
-       for (int i = 1; i <= maxline; ++i) {
-               if (t == fl_get_browser_line(browser, i)) {
-                       select(i);
-                       return true;
-               }
-       }
-       return false;  // t does not exist in browser
-}
-
-
-void Combox::select(int i)
-{
-       if (!browser || !button) return;
-       if (i > 0 && i <= fl_get_browser_maxline(browser)) sel = i;
-       fl_deactivate_object(button);
-
-       if (type == FL_COMBOX_INPUT)
-               fl_set_input(label, fl_get_browser_line(browser, sel));
-       else
-               fl_set_object_label(label, fl_get_browser_line(browser, sel));
-       fl_activate_object(button);
-}
-
-
-void Combox::add(int x, int y, int w, int hmin, int hmax)
-{
-       FL_OBJECT * obj;
-
-       switch (type) {
-       case FL_COMBOX_DROPLIST:
-       {
-               button = obj = fl_add_button(FL_NORMAL_BUTTON,
-                                            x+w-22, y, 22, hmin, "@2->");
-               fl_set_object_color(obj, FL_MCOL, FL_MCOL);
-               fl_set_object_dblbuffer(obj, 1);
-               fl_set_object_callback(obj, C_Combox_combo_cb, 0);
-               label = obj = fl_add_button(FL_NORMAL_TEXT, x, y, w-22, hmin, "");
-               fl_set_object_boxtype(obj, FL_DOWN_BOX);
-               fl_set_object_color(obj, FL_MCOL, FL_BLACK);
-               fl_set_object_lalign(obj, FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
-               fl_set_object_dblbuffer(obj, 1);
-               fl_set_object_callback(obj, C_Combox_combo_cb, 0);
-               break;
-       }
-       case FL_COMBOX_NORMAL:
-       {
-               button = obj = fl_add_button(FL_NORMAL_BUTTON, x, y, w, hmin, "");
-               fl_set_object_color(obj, FL_MCOL, FL_MCOL);
-               fl_set_object_boxtype(obj, FL_DOWN_BOX);
-               fl_set_object_callback(obj, C_Combox_combo_cb, 0);
-               fl_set_object_color(obj, FL_MCOL, FL_BLACK);
-               label = button;
-               break;
-       }
-       case FL_COMBOX_INPUT:
-       {
-               button = obj = fl_add_button(FL_NORMAL_BUTTON,
-                                            x+w-22, y, 22, hmin, "@2->");
-               fl_set_object_color(obj, FL_MCOL, FL_MCOL);
-               fl_set_object_callback(obj, C_Combox_combo_cb, 0);
-               label = obj = fl_add_input(FL_NORMAL_INPUT, x, y, w-22, hmin, "");
-               fl_set_object_boxtype(obj, FL_DOWN_BOX);
-               fl_set_object_return(obj, FL_RETURN_END_CHANGED);
-               fl_set_object_callback(obj, C_Combox_input_cb, 0);
-               //fl_set_object_color(obj, FL_MCOL, FL_BLACK);
-               //fl_set_object_lalign(obj,FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
-               break;
-       }
-       } // end of switch
-
-       label->u_vdata = this;
-       button->u_vdata = this;
-
-       // Hmm, it seems fl_create_browser is broken in xforms 0.86.
-       // We have to work around that by creating the dropped browser form
-       // at this point already. However, this means that we have
-       // to do a little hacking: (Asger)
-       FL_FORM * current_form = fl_current_form;
-       fl_end_form();
-
-       bw = w + 20;
-       bh = hmax - hmin - 12;
-
-       form = fl_bgn_form(FL_NO_BOX, bw, bh);
-       browser = obj = fl_add_browser(FL_HOLD_BROWSER, 0, 0, bw, bh, "");
-       fl_set_object_boxtype(obj, FL_UP_BOX);
-       fl_set_object_color(obj, FL_MCOL, FL_YELLOW);
-       fl_set_object_gravity(obj, NorthWestGravity, NorthWestGravity);
-       fl_set_object_callback(obj, C_Combox_combo_cb, 2);
-       fl_end_form();
-       browser->u_vdata = this;
-       form->u_vdata = browser;
-       fl_register_raw_callback(form,
-                                ButtonPressMask|KeyPressMask,
-                                C_Combox_peek_event);
-
-       // And revert to adding to the old form (Asger)
-       fl_addto_form(current_form);
-}
-
-
-namespace {
-
-Window save_window;
-
-} // namespace anon
-
-
-void Combox::redraw()
-{
-       if (browser) fl_redraw_object(browser);
-       if (button) fl_redraw_object(button);
-       if (label) fl_redraw_object(label);
-}
-
-void Combox::show()
-{
-       if (_pre) _pre();
-
-       int tmp;
-       XGetInputFocus(fl_get_display(), &save_window, &tmp); //BUG-Fix Dietmar
-       XFlush(fl_get_display());
-       if (button && type != FL_COMBOX_NORMAL) {
-               fl_set_object_label(button, "@2<-");
-               fl_redraw_object(button);
-       }
-
-       int const x = label->form->x + label->x;
-       int const y = label->form->y + label->y + label->h;
-
-       fl_set_form_position(form, x, y);
-       fl_show_form(form, FL_PLACE_POSITION, FL_NOBORDER, "");
-       if (sel > 0) {
-               fl_set_browser_topline(browser, sel);
-               fl_select_browser_line(browser, sel);
-       }
-       XGrabPointer(fl_get_display(), form->window, false,
-                    ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
-                    GrabModeAsync, GrabModeAsync,
-                    0, 0, 0);
-       XFlush(fl_get_display());
-}
-
-void Combox::hide(int who)
-{
-       if (!who && browser && label) {
-               sel = fl_get_browser(browser);
-
-               if (type == FL_COMBOX_INPUT)
-                       fl_set_input(label, fl_get_browser_line(browser, sel));
-               else
-                       fl_set_object_label(label,
-                                           fl_get_browser_line(browser, sel));
-//             if (callback) callback(sel, cb_arg);
-       }
-       XUngrabPointer(fl_get_display(), 0);
-       XFlush(fl_get_display());
-       if (form) {
-               fl_hide_form(form);
-               XSetInputFocus(fl_get_display(), save_window,
-                              RevertToParent, CurrentTime); // BUG-FIX-Dietmar
-               XFlush(fl_get_display());
-       }
-       if (button) {
-               if (type != FL_COMBOX_NORMAL) {
-                       fl_set_object_label(button, "@2->");
-                       fl_redraw_object(button);
-               }
-       }
-       if (!who && browser && label && callback)
-           callback(sel, cb_arg, this);
-       if (_post) _post();
-}
-
-
-void Combox::activate()
-{
-       if (browser)
-               fl_activate_object(browser);
-       if (button) {
-               fl_activate_object(button);
-               fl_set_object_lcol(button, FL_BLACK);
-       }
-       if (label) {
-               fl_activate_object(label);
-               fl_set_object_lcol(label, FL_BLACK);
-       }
-}
-
-
-void Combox::deactivate()
-{
-       if (browser)
-               fl_deactivate_object(browser);
-       if (button) {
-               fl_deactivate_object(button);
-               fl_set_object_lcol(button, FL_INACTIVE);
-       }
-       if (label) {
-               fl_deactivate_object(label);
-               fl_set_object_lcol(label, FL_INACTIVE);
-       }
-}
-
-
-void Combox::input_cb(FL_OBJECT * ob, long)
-{
-       Combox * combo = static_cast<Combox*>(ob->u_vdata);
-
-       char const * text = fl_get_input(ob);
-
-       combo->addto(text ? string(text) : string());
-       combo->is_empty = false;
-}
-
-
-void Combox::combo_cb(FL_OBJECT * ob, long data)
-{
-       Combox * combo = static_cast<Combox*>(ob->u_vdata);
-       switch (data) {
-       case 0:
-       {
-               int const i = combo->get();
-               switch (fl_get_button_numb(ob)) {
-               case 2:
-               {
-                       combo->select(i - 1);
-                       if (combo->callback)
-                               combo->callback(combo->sel,
-                                               combo->cb_arg, combo);
-                       break;
-               }
-               case 3:
-               {
-                       combo->select(i + 1);
-                       if (combo->callback)
-                               combo->callback(combo->sel,
-                                               combo->cb_arg, combo);
-                       break;
-               }
-               default: combo->show(); break;
-               }
-               break;
-       }
-       case 2:
-               combo->hide();
-               break;
-       }
-}
-
-
-int Combox::peek_event(FL_FORM * form, void * xev)
-{
-       FL_OBJECT * ob = static_cast<FL_OBJECT *>(form->u_vdata);
-       Combox * combo = static_cast<Combox*>(ob->u_vdata);
-
-       // below mouse does not work like we need it
-       if (static_cast<XEvent *>(xev)->type == ButtonPress && (
-               static_cast<XEvent *>(xev)->xbutton.x - ob->x < 0 ||
-               static_cast<XEvent *>(xev)->xbutton.x - ob->x > ob->w ||
-               static_cast<XEvent *>(xev)->xbutton.y - ob->y < 0 ||
-               static_cast<XEvent *>(xev)->xbutton.y - ob->y > ob->h)) {
-               combo->hide(1);
-               return 1;
-       }
-
-       if (static_cast<XEvent*>(xev)->type != KeyPress) return 0;
-
-       char s_r[10]; s_r[9] = '\0';
-       KeySym keysym_return;
-       XLookupString(&static_cast<XEvent*>(xev)->xkey, s_r, 10,
-                             &keysym_return, 0);
-       XFlush(fl_get_display());
-       switch (keysym_return) {
-       case XK_Down:
-#ifdef XK_KP_Down
-       case XK_KP_Down:
-#endif
-               if (fl_get_browser(combo->browser) <
-                   fl_get_browser_maxline(combo->browser))
-                       fl_select_browser_line(combo->browser,
-                                              fl_get_browser(combo->browser)+1);
-               if (fl_get_browser(combo->browser)>=
-                   fl_get_browser_topline(combo->browser) +
-                   fl_get_browser_screenlines(combo->browser))
-                       fl_set_browser_topline(combo->browser,
-                                              fl_get_browser(combo->browser)
-                                              - fl_get_browser_screenlines(combo->browser)+1);
-               if (fl_get_browser(combo->browser)<
-                   fl_get_browser_topline(combo->browser))
-                       fl_set_browser_topline(combo->browser,
-                                              fl_get_browser(combo->browser));
-               return 1;
-       case XK_Up:
-#ifdef XK_KP_Up
-       case XK_KP_Up:
-#endif
-               if (fl_get_browser(combo->browser) > 1)
-                       fl_select_browser_line(combo->browser,
-                                              fl_get_browser(combo->browser)-1);
-               if (fl_get_browser(combo->browser)>=
-                   fl_get_browser_topline(combo->browser) +
-                   fl_get_browser_screenlines(combo->browser))
-                       fl_set_browser_topline(combo->browser,
-                                              fl_get_browser(combo->browser)
-                                              - fl_get_browser_screenlines(combo->browser)+1);
-               if (fl_get_browser(combo->browser) <
-                   fl_get_browser_topline(combo->browser))
-                       fl_set_browser_topline(combo->browser,
-                                              fl_get_browser(combo->browser));
-               return 1;
-       case XK_Return:
-#ifdef XK_KP_Enter
-       case XK_KP_Enter:
-#endif
-               combo->hide();
-               return 1;
-       case XK_Escape:
-               combo->hide(1);
-               return 1;
-       }
-       return 0;
-}
-
-
-#ifdef TESTCOMBO
-typedef struct {
-       FL_FORM *test;
-       FL_OBJECT *bar;
-       void *vdata;
-       long ldata;
-} FD_test;
-
-//Combox combo(FL_COMBOX_DROPLIST);
-Combox combo(FL_COMBOX_INPUT);
-
-FD_test *fd_test;
-
-FD_test *create_form_test(void)
-{
-   FL_OBJECT *obj;
-   FD_test *fdui = (FD_test *) fl_calloc(1, sizeof(*fdui));
-
-   fdui->test = fl_bgn_form(FL_NO_BOX, 320, 190);
-   obj = fl_add_box(FL_UP_BOX, 0, 0, 320, 190, "");
-   obj = fl_add_box(FL_DOWN_BOX, 10, 50, 300, 110, "");
-   obj = fl_add_button(FL_NORMAL_BUTTON, 250, 10, 50, 30, _("Done"));
-   combo.add(10, 15, 120, 25, 135);
-   fl_end_form();
-
-  return fdui;
-}
-
-void combo_cb(int i)
-{
-   fprintf(stderr, "selected %d:%s\n", i, combo.getline());
-}
-
-int main(int argc, char *argv[])
-{
-       //int n1;
-
-   // Same defaults as in lyx
-   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.borderWidth = -2;
-   fl_set_defaults(FL_PDButtonFontSize, &cntl);
-   fl_set_defaults(FL_PDBrowserFontSize, &cntl);
-   fl_set_defaults(FL_PDLabelFontSize, &cntl);
-   fl_set_defaults(FL_PDChoiceFontSize, &cntl);
-   fl_set_defaults(FL_PDInputFontSize, &cntl);
-   fl_set_defaults(FL_PDBorderWidth, &cntl);
-   fl_initialize(&argc, argv, 0, 0, 0);
-
-   fd_test = create_form_test();
-
-   /* fill-in form initialization code */
-   combo.addline("Title");
-   combo.addline("Author");
-   combo.addline("Date");
-   combo.addline("Abstract");
-   combo.addline("Chapter");
-   combo.addline("Section");
-   combo.addline("Subsection");
-   combo.addline("List");
-   combo.addline("Description");
-   combo.addline("Verse");
-   combo.addline("Verbatim");
-   combo.setcallback(combo_cb);
-//   combo.select(4);
-
-   /* show the first form */
-   fl_show_form(fd_test->test, FL_PLACE_CENTER, FL_FULLBORDER, "test");
-   fl_do_forms();
-   return 0;
-}
-
-#endif
diff --git a/src/frontends/xforms/combox.c b/src/frontends/xforms/combox.c
new file mode 100644 (file)
index 0000000..3dc9bea
--- /dev/null
@@ -0,0 +1,460 @@
+/**
+ * \file combox.c
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author Angus Leeming
+ *
+ * This is a rewrite of Alejandro's C++ Combox class, originally written
+ * for LyX in 1996. The rewrite turns it into a native xforms widget.
+ */
+#include <config.h>
+
+#include FORMS_H_LOCATION
+#include "combox.h"
+#include "freebrowser.h"
+
+
+extern void fl_add_child(FL_OBJECT *, FL_OBJECT *);
+extern void fl_addto_freelist(void *);
+
+
+typedef struct {
+     /** A pointer to the parent widget */
+    FL_OBJECT * combox;
+
+    FL_FREEBROWSER * browser;
+    int browser_height;
+
+    /** The browser will be displayed either below or above the main body. */
+    int browser_position;
+
+    /**  button_state displays a down or up arrow depending on whether the
+     *  browser is visible or not.
+     *   Click on it to toggle the browser.
+     */
+    FL_OBJECT * button_state;
+
+    /**  button_chosen displays the current selection from the browser.
+     *  Click on it to toggle the browser.
+     */
+    FL_OBJECT * button_chosen;
+} COMBOX_SPEC;
+
+
+enum { ACTIVATE, DEACTIVATE };
+
+enum { COMBOX_OPEN, COMBOX_CLOSED };
+
+
+/* function declarations */
+static int combox_pre(FL_OBJECT *, int, FL_Coord, FL_Coord, int, void *);
+static int combox_post(FL_OBJECT *, int, FL_Coord, FL_Coord, int, void *);
+static int combox_handle(FL_OBJECT *, int, FL_Coord, FL_Coord, int, void *);
+
+static void update_button_chosen(FL_FREEBROWSER * fb, int action);
+static void chosen_cb(FL_OBJECT * ob, long data);
+static void state_cb(FL_OBJECT * ob, long data);
+
+static void show_browser(COMBOX_SPEC * sp);
+static void set_activation(FL_OBJECT * ob, int activation);
+static void set_state_label(COMBOX_SPEC * sp, int state);
+static void attrib_change(COMBOX_SPEC * sp);
+
+
+FL_OBJECT * fl_create_combox(int type,
+                            FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
+                            char const * label)
+{
+    FL_OBJECT * ob;
+    FL_OBJECT * button;
+    COMBOX_SPEC * sp;
+
+    /* The width and x-position of button_state, respectively. */
+    FL_Coord const ws = 0.7 * h;
+    FL_Coord const xs = x + w - ws;
+
+    ob = fl_make_object(FL_COMBOX, type, x, y, w, h, label, combox_handle);
+    ob->align = FL_ALIGN_LEFT;
+
+    sp = ob->spec = fl_calloc(1, sizeof(COMBOX_SPEC));
+    sp->combox = ob;
+    sp->browser_height = 100;
+    sp->browser_position = FL_FREEBROWSER_BELOW;
+
+    sp->browser = fl_create_freebrowser(sp);
+    sp->browser->callback = update_button_chosen;
+
+    sp->button_state = fl_add_button(FL_NORMAL_BUTTON, xs, y, ws, h, "");
+
+    button = sp->button_state;
+    fl_set_object_lalign(button, FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
+    fl_set_object_callback(button, state_cb, 0);
+    fl_set_object_posthandler(button, combox_post);
+    fl_set_object_prehandler(button,  combox_pre);
+    set_state_label(sp, COMBOX_CLOSED);
+
+    set_activation(button, DEACTIVATE);
+    button->parent = ob;
+    button->u_vdata = sp;
+
+    sp->button_chosen = fl_add_button(FL_NORMAL_TEXT, x, y, (w - ws), h, "");
+
+    button = sp->button_chosen;
+    fl_set_object_boxtype(button, FL_FRAME_BOX);
+    fl_set_object_lalign(button, FL_ALIGN_CENTER|FL_ALIGN_INSIDE);
+    fl_set_object_callback(button, chosen_cb, 0);
+    fl_set_object_posthandler(button, combox_post);
+    fl_set_object_prehandler(button,  combox_pre);
+    set_activation(button, DEACTIVATE);
+    button->parent = ob;
+    button->u_vdata = sp;
+
+    return ob;
+}
+
+
+FL_OBJECT * fl_add_combox(int type,
+                         FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
+                         char const * label)
+{
+    FL_OBJECT * ob = fl_create_combox(type, x, y, w, h, label);
+    COMBOX_SPEC * sp = ob->spec;
+
+    fl_add_child(ob, sp->button_state);
+    fl_add_child(ob, sp->button_chosen);
+
+    fl_add_object(fl_current_form, ob);
+    return ob;
+}
+
+
+void fl_set_combox_browser_height(FL_OBJECT * ob, int bh)
+{
+    COMBOX_SPEC * sp;
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return;
+
+    sp = ob->spec;
+    sp->browser_height = bh;
+}
+
+
+void fl_set_combox_position(FL_OBJECT * ob, int position)
+{
+    COMBOX_SPEC * sp;
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return;
+
+    sp = ob->spec;
+    sp->browser_position = (position == FL_FREEBROWSER_ABOVE) ?
+       FL_FREEBROWSER_ABOVE : FL_FREEBROWSER_BELOW;
+
+    set_state_label(sp, COMBOX_CLOSED);
+}
+
+
+void fl_clear_combox(FL_OBJECT * ob)
+{
+    COMBOX_SPEC * sp;
+    FL_OBJECT * browser;
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return;
+
+    sp = ob->spec;
+    browser = fl_get_freebrowser_browser(sp->browser);
+
+    fl_clear_browser(browser);
+    fl_set_object_label(sp->button_chosen, "");
+}
+
+
+void fl_addto_combox(FL_OBJECT * ob, char const * text)
+{
+    COMBOX_SPEC * sp;
+    FL_OBJECT * browser;
+    int i;
+    int j;
+    char line[128];
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return;
+
+    sp = ob->spec;
+    browser = fl_get_freebrowser_browser(sp->browser);
+
+    /* Split the string on '|' boundaries. */
+    i = j = 0;
+    for (; text[i] != '\0'; ++i) {
+       if (text[i] == '|') {
+           line[j] = '\0';
+           fl_add_browser_line(browser, line);
+           j = 0;
+       } else {
+           line[j++] = text[i];
+       }
+    }
+
+    if (j != 0)
+       {
+           line[j] = '\0';
+           fl_add_browser_line(browser, line);
+       }
+
+    /* By default the first item is selected */
+    if (!fl_get_browser(browser)) {
+       fl_set_object_label(sp->button_chosen, text);
+       set_activation(sp->button_chosen, ACTIVATE);
+       set_activation(sp->button_state,  ACTIVATE);
+    }
+}
+
+
+void fl_set_combox(FL_OBJECT * ob, int sel)
+{
+    COMBOX_SPEC * sp;
+    FL_OBJECT * browser;
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return;
+
+    sp = ob->spec;
+    browser = fl_get_freebrowser_browser(sp->browser);
+
+    if (sel < 1 || sel > fl_get_browser_maxline(browser))
+       return;
+
+    fl_select_browser_line(browser, sel);
+    fl_set_object_label(sp->button_chosen, fl_get_browser_line(browser, sel));
+}
+
+
+int fl_get_combox(FL_OBJECT * ob)
+{
+    COMBOX_SPEC * sp;
+    FL_OBJECT * browser;
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return 0;
+
+    sp = ob->spec;
+    browser = fl_get_freebrowser_browser(sp->browser);
+    return fl_get_browser(browser);
+}
+
+
+char const * fl_get_combox_text(FL_OBJECT * ob)
+{
+    COMBOX_SPEC * sp;
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return 0;
+
+    sp = ob->spec;
+    return sp->button_chosen->label;
+}
+
+
+char const * fl_get_combox_line(FL_OBJECT * ob, int line)
+{
+    COMBOX_SPEC * sp;
+    FL_OBJECT * browser;
+    int maxlines;
+
+    if (line < 1 || !ob || ob->objclass != FL_COMBOX)
+       return 0;
+
+    sp = ob->spec;
+    browser = fl_get_freebrowser_browser(sp->browser);
+
+    maxlines = fl_get_browser_maxline(browser);
+    if (line > maxlines)
+       return 0;
+
+    return fl_get_browser_line(browser, line);
+}
+
+
+int fl_get_combox_maxitems(FL_OBJECT * ob)
+{
+    COMBOX_SPEC * sp;
+    FL_OBJECT * browser;
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return 0;
+
+    sp = ob->spec;
+    browser = fl_get_freebrowser_browser(sp->browser);
+    return fl_get_browser_maxline(browser);
+}
+
+
+void fl_show_combox_browser(FL_OBJECT * ob)
+{
+    if (!ob || ob->objclass != FL_COMBOX)
+       return;
+
+    show_browser(ob->spec);
+}
+
+
+void fl_hide_combox_browser(FL_OBJECT * ob)
+{
+    COMBOX_SPEC * sp;
+
+    if (!ob || ob->objclass != FL_COMBOX)
+       return;
+
+    sp = ob->spec;
+    fl_free_freebrowser(sp->browser);
+}
+
+
+static int combox_pre(FL_OBJECT * ob, int ev, FL_Coord mx, FL_Coord my,
+                     int key, void *xev)
+{
+    COMBOX_SPEC * sp = ob->u_vdata;
+    FL_OBJECT * combox = sp->combox;
+
+    return combox->prehandle ?
+       combox->prehandle(combox, ev, mx, my, key, xev) : 0;
+}
+
+
+static int combox_post(FL_OBJECT * ob, int ev, FL_Coord mx, FL_Coord my,
+                      int key, void *xev)
+{
+    COMBOX_SPEC * sp = ob->u_vdata;
+    FL_OBJECT * combox = sp->combox;
+
+    return combox->posthandle ?
+       combox->posthandle(combox, ev, mx, my, key, xev) : 0;
+}
+
+
+static int combox_handle(FL_OBJECT * ob, int event, FL_Coord mx, FL_Coord my,
+                        int key, void * ev)
+{
+    if (!ob || ob->objclass != FL_COMBOX)
+       return 0;
+
+    switch (event) {
+    case FL_DRAW:
+       attrib_change(ob->spec);
+       /* Fall through */
+    case FL_DRAWLABEL:
+       fl_draw_object_label(ob);
+       break;
+    case FL_SHORTCUT:
+       show_browser(ob->spec);
+       break;
+    case FL_FREEMEM: {
+       COMBOX_SPEC * sp = ob->spec;
+       fl_free_freebrowser(sp->browser);
+       /* children take care of themselves, but we must make sure that
+          sp itself is free-d eventually. */
+       fl_addto_freelist(sp);
+       break;
+    }
+    }
+    return 0;
+}
+
+
+static void set_activation(FL_OBJECT * ob, int activation)
+{
+    switch (activation) {
+    case ACTIVATE:
+       fl_activate_object(ob);
+       fl_set_object_lcol(ob, FL_LCOL);
+       break;
+    case DEACTIVATE:
+       fl_deactivate_object(ob);
+       fl_set_object_lcol(ob, FL_INACTIVE);
+    }
+}
+
+
+static void show_browser(COMBOX_SPEC * sp)
+{
+    FL_OBJECT * ob = sp->combox;
+
+    /* The browser dimensions. */
+    FL_Coord const bw = ob->w + 20;
+    FL_Coord const bh = sp->browser_height;
+
+    FL_Coord const abs_x = ob->form->x + ob->x;
+
+    FL_Coord abs_y = ob->form->y + ob->y;
+    abs_y += (sp->browser_position == FL_FREEBROWSER_BELOW) ? ob->h : -bh;
+
+    set_state_label(sp, COMBOX_OPEN);
+    fl_show_freebrowser(sp->browser, abs_x, abs_y, bw, bh);
+}
+
+
+static void state_cb(FL_OBJECT * ob, long data)
+{
+    show_browser(ob->u_vdata);
+}
+
+
+static void chosen_cb(FL_OBJECT * ob, long data)
+{
+    show_browser(ob->u_vdata);
+}
+
+
+static void update_button_chosen(FL_FREEBROWSER * fb, int action)
+{
+    COMBOX_SPEC * sp = fb->parent;
+
+    FL_OBJECT * browser = fl_get_freebrowser_browser(sp->browser);
+    FL_OBJECT * combox = sp->combox;
+    if (!browser || !combox) return;
+
+    set_state_label(sp, COMBOX_CLOSED);
+
+    if (action == 1) {
+       int const sel = fl_get_browser(browser);
+       char const * const text = fl_get_browser_line(browser, sel);
+       fl_set_object_label(sp->button_chosen, text);
+       fl_call_object_callback(combox);
+    }
+}
+
+
+static void set_state_label(COMBOX_SPEC * sp, int state)
+{
+    char const * const up   = "@2<-";
+    char const * const down = "@2->";
+    char const * label = 0;
+    if (sp->browser_position == FL_FREEBROWSER_BELOW) {
+       label = (state == COMBOX_OPEN) ? up : down;
+    } else {
+       label = (state == COMBOX_OPEN) ? down : up;
+    }
+    fl_set_object_label(sp->button_state, label);
+    fl_redraw_object(sp->button_state);
+}
+
+
+static void attrib_change(COMBOX_SPEC * sp)
+{
+    FL_OBJECT * parent = sp->combox;
+    FL_OBJECT * button = sp->button_chosen;
+
+    button->boxtype = parent->boxtype;
+    button->col1    = parent->col1;
+    button->col2    = parent->col2;
+    button->bw      = parent->bw;
+
+    button = sp->button_state;
+
+    /* The boxtype is not changed */
+    button->col1    = parent->col1;
+    button->col2    = parent->col2;
+    button->bw      = parent->bw;
+}
index 8b901944eb1932183c1ef850a7d666fcb0f429a4..50cdb6aa8c0ffe535604c3a0d457f696c581e4b6 100644 (file)
-// -*- C++ -*-
 /**
  * \file combox.h
- * Copyright 1996 Alejandro Aguilar Sierra
- * This file is part of LyX, the document processor.
- * Licence details can be found in the file COPYING.
+ * \author Angus Leeming
  *
- * \author Alejandro Aguilar Sierra
- *
- * Full author contact details are available in file CREDITS
- */
-
-/* A combination of two objects (a button and a browser) is encapsulated to
- * get a combobox-like object. All XForms functions are hidden.
- *
- * Change log:
- *
- *  2/06/1996,   Alejandro Aguilar Sierra
- *    Created and tested.
- *
- *  4/06/1996,   Alejandro Aguilar Sierra
- *    Added droplist mode (a button with a black down arrow at right)
- *    and support for middle and right buttons, as XForms choice object.
+ * A combination of two objects (a button and a browser) is encapsulated to
+ * get a combobox-like object.
  */
 
-#ifndef COMBOX_H
-#define COMBOX_H
-
+#ifndef FL_COMBOX_H
+#define FL_COMBOX_H
 
-#include FORMS_H_LOCATION
-#include <cstdlib>
-#include "LString.h"
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
 
-///
-enum combox_type {
-       ///
-       FL_COMBOX_NORMAL,
-       ///
-       FL_COMBOX_DROPLIST,
-       ///
-       FL_COMBOX_INPUT
+/** This will eventually be moved into the enum of in-built widgets
+    in forms.h. */
+enum {
+    FL_COMBOX = 200
 };
 
-class Combox;
-
-/// callback prototype
-typedef void (*FL_COMBO_CB) (int, void *, Combox *);
-/// pre post prototype
-typedef void (*FL_COMBO_PRE_POST) ();
-
-
-///
-class Combox {
-public:
-       ///
-       explicit Combox(combox_type t = FL_COMBOX_NORMAL);
-       ///
-       ~Combox();
-
-       /** To add this object to a form. Note that there are two heights
-        *  for normal (button) and expanded (browser) mode each.
-        */
-       void add(int x, int y, int w, int hmin, int hmax);
-
-       /// Add lines. Same as for fl_browser object
-       void addline(string const &);
-       /// Add lines. Same as for fl_browser object
-       void addto(string const &);
-
-       /// Returns the selected item
-       int get() const;
-
-       /// Returns a pointer to the selected line of text
-       string const getline() const;
-
-       ///  Select an arbitrary item
-       void select(int);
-       ///
-       bool select(string const &);
-
-       ///  Clear all the list
-       void clear();
-
-       /// Is the combox cleared (empty)
-       bool empty() const { return is_empty; }
-
-       /// Remove the objects from the form they are in.
-       void remove();
-
-       /**
-        * Assign a callback to this object. The callback should be a void
-        * function with a int, a void pointer, and a Combox pointer as
-        * parameters.
-       */
-       void setcallback(FL_COMBO_CB, void *);
-
-       ///  Pre handler
-       void setpre(FL_COMBO_PRE_POST);
-       /// Post handler
-       void setpost(FL_COMBO_PRE_POST);
-
-       ///  XForms attributes
-       void resize(unsigned);
-       ///
-       void gravity(unsigned, unsigned);
-       ///
-       void activate();
-       ///
-       void deactivate();
-       ///
-       void shortcut(string const &, int);
-       ///
-       void redraw();
-       ///
-       void show();
-       ///
-       static void combo_cb(FL_OBJECT *, long);
-       ///
-       static void input_cb(FL_OBJECT *, long);
-       ///
-       static int  peek_event(FL_FORM *, void *);
- protected:
-       /// At least Hide should not be public
-       void hide(int who = 0);
-       ///
-       FL_OBJECT * browser;
- private:
-       ///
-       combox_type type;
-       ///
-       int bw;
-       ///
-       int bh;
-       ///
-       int sel;
-       ///
-       bool is_empty;
-       ///
-       FL_COMBO_CB callback;
-       ///
-       void * cb_arg;
-       ///
-       FL_COMBO_PRE_POST _pre;
-       ///
-       FL_COMBO_PRE_POST _post;
-       ///
-       FL_OBJECT * button;
-       ///
-       FL_OBJECT * label;
-       ///
-       FL_FORM* form;
+/** The types of combox. At the moment, there's only one. */
+enum {
+    FL_DROPLIST_COMBOX
 };
 
+/** A function to create a combox widget.
+ *  \param type is, as yet, unused. there is only one type of combox.
+ *  \param x, \param y: the x,y coordinates of the upper left hand corner
+ *  of the widget, relative to the parent form'd origin.
+ *  \param w, \param h: the widget's dimensions.
+ *  \param label: the widget's label as it appears on the GUI.
+ */
+FL_EXPORT FL_OBJECT *
+fl_create_combox(int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
+                char const * label);
 
+/** A function to create a combox widget and add it to the parent form.
+ *  \see fl_create_combox() for an explanation of the argument list.
+ */
+FL_EXPORT FL_OBJECT *
+fl_add_combox(int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h,
+             char const * label);
 
-//-----------------  Inline methods  ---------------------------
-
-inline
-void Combox::addto(string const & text)
-{
-       if (browser) {
-               fl_addto_browser(browser, text.c_str());
-               is_empty = false;
-       }
-}
-
-
-inline
-void Combox::resize(unsigned r)
-{
-   fl_set_object_resize(button, r);
-   if (label!= button) fl_set_object_resize(label, r);
-}
-
-
-inline
-void Combox::gravity(unsigned g1, unsigned g2)
-{
-   fl_set_object_gravity(button, g1, g2);
-   if (label!= button) fl_set_object_gravity(label, g1, g2);
-}
-
+/** The combox browser has a default height of 100 pixels. Adjust to suit. */
+FL_EXPORT void fl_set_combox_browser_height(FL_OBJECT * ob, int bh);
 
-inline
-void Combox::shortcut(string const & s, int i)
-{
-   if (button)
-      fl_set_object_shortcut(button, s.c_str(), i);
-}
+/** The browser will be displayed either below or above the button,
+ *  dependent upon \param position.
+ */
+FL_EXPORT void fl_set_combox_position(FL_OBJECT * ob, int position);
 
+/** Empty the browser and the combox, \param ob. */
+FL_EXPORT void fl_clear_combox(FL_OBJECT * ob);
 
-inline
-void Combox::setcallback(FL_COMBO_CB cb, void * a = 0)
-{
-   callback = cb;
-   cb_arg = a;
-}
+/** Add a line to the combox browser.*/
+FL_EXPORT void fl_addto_combox(FL_OBJECT * ob, char const * text);
 
+/** Set the combox to return line \param choice of the combox browser. */
+FL_EXPORT void fl_set_combox(FL_OBJECT * ob, int choice);
 
-inline
-void Combox::setpre(FL_COMBO_PRE_POST cb)
-{
-       _pre = cb;
-}
+/** \return the currently selected line of the combox browser. */
+FL_EXPORT int fl_get_combox(FL_OBJECT * ob);
 
+/** \return the contents of the combox.
+ *  (Also the contents of currently selected line of the combox browser.)
+ */
+FL_EXPORT char const * fl_get_combox_text(FL_OBJECT * ob);
 
-inline
-void Combox::setpost(FL_COMBO_PRE_POST cb)
-{
-       _post = cb;
-}
+/** \return the contents of \param line of the combox browser. */
+FL_EXPORT char const * fl_get_combox_line(FL_OBJECT * ob, int line);
 
+/** \return the number of items in the combox browser. */
+FL_EXPORT int fl_get_combox_maxitems(FL_OBJECT * ob);
 
-inline
-int Combox::get() const
-{
-   return sel;
-}
+/** Show the browser */
+void fl_show_combox_browser(FL_OBJECT * ob);
 
+/** Hide the browser */
+void fl_hide_combox_browser(FL_OBJECT * ob);
 
-inline
-string const Combox::getline() const
-{
-    if (type == FL_COMBOX_INPUT)
-      return fl_get_input(label);
-    else
-      return (browser && sel > 0) ?
-             string(fl_get_browser_line(browser, sel)) : string();
+#if defined(__cplusplus)
 }
+#endif
 
 #endif
index 6c5dac9687361d2566828863ad756d618a2aa770..553eed26979c4bb37ce7ab1e692eeb25f2c74b77 100644 (file)
@@ -41,9 +41,10 @@ Being more explicit:
        FL_TEXT           | text
 
 The only exceptions to this are objects that are to be converted in the sed
-scripts. At the moment this applies only to bmtable:
+scripts. At the moment this applies only to bmtable and to combox:
 
        Convert an FL_BUTTON to a FL_BMTABLE by using prefix "bmtable".
+       Convert an FL_CHOICE to a FL_COMBOX by using prefix "combox".
 
 Enter the full name of the callback eg.:
         C_FormBaseOkCB
index 7a8f3754b8846551898b9fcc9ff28f42094d0fc4..4c826186c071c9cba1cb0f2075eecb7fdd36b7dd 100644 (file)
@@ -140,9 +140,12 @@ INTRO_MESSAGE ${TMP}
 echo "#include <config.h>" >> ${TMP}
 echo "#include \"forms_gettext.h\"" >> ${TMP}
 echo "#include \"gettext.h\"" >> ${TMP}
+echo "#include FORMS_H_LOCATION" >> ${TMP}
 
 grep bmtable ${CIN} > /dev/null &&
        echo "#include \"bmtable.h\"" >> ${TMP}
+grep combox ${CIN} > /dev/null &&
+       echo "#include \"combox.h\"" >> ${TMP}
 
 sed -f ${FDFIXC} < ${CIN} >> ${TMP}
 
index 93b7722862e49845967a0f6f2046ecc1353c2cfd..b2db372ac7c294995732341976779026cfe15117 100644 (file)
@@ -22,8 +22,8 @@ s/[   ]*$//
 /^\/\*-----/d
 
 
-# Replace "forms.h" by FORMS_H_LOCATION in the #include directives
-s/#include \"forms\.h\"/#include FORMS_H_LOCATION/
+# Remove '#include "forms.h"'. It is replace by a macro in fdfix.sh.
+/^#include \"forms\.h\"/d
 
 
 # Pretty formatting; replace all leading whitespace with a tab
@@ -74,6 +74,11 @@ s/\( fdui->form\)\(.*bgn_form.*\)/\1\2\
 /bmtable/ s/fl_add_button/fl_add_bmtable/
 
 
+# For all lines containing "combox",
+# replace "fl_add_choice" with "fl_add_combox"
+/combox/ s/fl_add_choice([^,]*/fl_add_combox(FL_DROPLIST_COMBOX/
+
+
 # For all lines containing fl_add_choice,
 # add a line that turns off the title. (These titles can contain meta-chars
 # that just look nasty ;-)
index 03d81c45eb32112dca55db8d76228574fb2ff042..63dee92a69bcdb0b682b5dab2291cdec5ec36ab6 100644 (file)
@@ -11,7 +11,7 @@ SnapGrid: 5
 Name: form_character
 Width: 300
 Height: 415
-Number of Objects: 15
+Number of Objects: 14
 
 --------------------
 class: FL_BOX
@@ -126,37 +126,19 @@ class: FL_CHOICE
 type: DROPLIST_CHOICE
 box: 95 175 190 30
 boxtype: FL_FRAME_BOX
-colors: FL_COL1 FL_BLACK
+colors: FL_COL1 FL_COL1
 alignment: FL_ALIGN_LEFT
 style: FL_NORMAL_STYLE
 size: FL_NORMAL_SIZE
 lcol: FL_BLACK
-label: Language:
+label: Language:|#L
 shortcut: 
 resize: FL_RESIZE_X
 gravity: FL_NorthWest FL_NorthEast
-name: choice_language
+name: combox_language
 callback: C_FormDialogView_InputCB
 argument: 0
 
---------------------
-class: FL_TEXT
-type: NORMAL_TEXT
-box: 11 170 84 40
-boxtype: FL_FLAT_BOX
-colors: FL_COL1 FL_MCOL
-alignment: FL_ALIGN_RIGHT|FL_ALIGN_INSIDE
-style: FL_NORMAL_STYLE
-size: FL_NORMAL_SIZE
-lcol: FL_BLACK
-label: Language:
-shortcut: 
-resize: FL_RESIZE_ALL
-gravity: FL_NoGravity FL_NoGravity
-name: 
-callback: 
-argument: 
-
 --------------------
 class: FL_CHECKBUTTON
 type: PUSH_BUTTON
index 6b721417c6da23d3d674d7dde8629b8727dac70b..e2f93c1b598243ede108ab8fe59c80a59ecfd71b 100644 (file)
@@ -819,19 +819,19 @@ argument: 0
 
 --------------------
 class: FL_CHOICE
-type: NORMAL_CHOICE
+type: DROPLIST_CHOICE
 box: 110 10 160 25
 boxtype: FL_FRAME_BOX
-colors: FL_COL1 FL_BLACK
+colors: FL_COL1 FL_COL1
 alignment: FL_ALIGN_LEFT
 style: FL_NORMAL_STYLE
 size: FL_NORMAL_SIZE
 lcol: FL_BLACK
-label: Class:|#l
+label: Class:|#C
 shortcut: 
 resize: FL_RESIZE_ALL
 gravity: FL_NoGravity FL_NoGravity
-name: choice_doc_class
+name: combox_doc_class
 callback: C_FormBaseInputCB
 argument: 0
 
@@ -1330,10 +1330,10 @@ argument:
 
 --------------------
 class: FL_CHOICE
-type: NORMAL_CHOICE
+type: DROPLIST_CHOICE
 box: 120 35 190 25
 boxtype: FL_FRAME_BOX
-colors: FL_COL1 FL_BLACK
+colors: FL_COL1 FL_COL1
 alignment: FL_ALIGN_LEFT
 style: FL_NORMAL_STYLE
 size: FL_NORMAL_SIZE
@@ -1342,7 +1342,7 @@ label: Language:|#L
 shortcut: 
 resize: FL_RESIZE_ALL
 gravity: FL_NoGravity FL_NoGravity
-name: choice_language
+name: combox_language
 callback: C_FormBaseInputCB
 argument: 0
 
index ef0ce498f35a30ff6bb094899b4020fcb1a3173f..acde64cdd04e90551816cb138d4ef517e1e3a992 100644 (file)
@@ -1605,7 +1605,7 @@ class: FL_CHOICE
 type: NORMAL_CHOICE
 box: 231 56 200 30
 boxtype: FL_FRAME_BOX
-colors: FL_COL1 FL_BLACK
+colors: FL_COL1 FL_COL1
 alignment: FL_ALIGN_LEFT
 style: FL_NORMAL_STYLE
 size: FL_DEFAULT_SIZE
@@ -1614,7 +1614,7 @@ label: Default language:|#l
 shortcut: 
 resize: FL_RESIZE_ALL
 gravity: FL_NoGravity FL_NoGravity
-name: choice_default_lang
+name: combox_default_lang
 callback: C_FormBaseInputCB
 argument: 0
 
diff --git a/src/frontends/xforms/freebrowser.c b/src/frontends/xforms/freebrowser.c
new file mode 100644 (file)
index 0000000..0ab13e7
--- /dev/null
@@ -0,0 +1,228 @@
+/**
+ * \file freebrowser.c
+ *
+ * \author Alejandro Aguilar Sierra
+ * \author Angus Leeming
+ *
+ * This is a rewrite of Alejandro's C++ Combox class, originally written
+ * for LyX in 1996. The rewrite turns it into a native xforms widget.
+ */
+#include <config.h>
+
+#include FORMS_H_LOCATION
+#include "freebrowser.h"
+#include <ctype.h> /* isprint */
+
+extern void fl_hide_tooltip(void);
+
+static void browser_cb(FL_OBJECT * ob, long data);
+
+static int peek_event(FL_FORM * form, void * xev);
+
+
+FL_FREEBROWSER * fl_create_freebrowser(void * parent)
+{
+    FL_FORM * current_form = fl_current_form;
+    FL_FREEBROWSER * fb = fl_calloc(1, sizeof(FL_FREEBROWSER));
+    FL_OBJECT * ob;
+
+    /* Default size */
+    FL_Coord const w = 100;
+    FL_Coord const h = 100;
+
+    fb->parent = parent;
+    fb->callback = 0;
+    fb->want_printable = 0;
+    fb->last_printable = 0;
+
+    if (current_form) fl_end_form();
+    fb->form = fl_bgn_form(FL_NO_BOX, w, h);
+
+    fb->form->u_vdata = fb;
+    fl_register_raw_callback(fb->form, ButtonPressMask|KeyPressMask,
+                            peek_event);
+
+    ob = fb->browser = fl_add_browser(FL_HOLD_BROWSER, 0, 0, w, h, "");
+    ob->u_vdata = fb;
+    fl_set_object_boxtype(ob, FL_UP_BOX);
+    fl_set_object_color(ob, FL_MCOL, FL_YELLOW);
+    fl_set_object_gravity(ob, NorthWestGravity, SouthEastGravity);
+    fl_set_object_callback(ob, browser_cb, 0);
+    fl_end_form();
+
+    if (current_form)
+       fl_addto_form(current_form);
+
+    return fb;
+}
+
+
+void fl_free_freebrowser(FL_FREEBROWSER * fb)
+{
+    if (!fb)
+       return;
+
+    if (fb->form)
+       fl_free_form(fb->form);
+
+    fl_free(fb);
+    fb = 0;
+}
+
+
+void fl_show_freebrowser(FL_FREEBROWSER * fb,
+                        FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h)
+{
+    int tmp;
+    int const pos = fl_get_browser(fb->browser);
+
+    fl_set_form_geometry(fb->form, x, y, w, h);
+
+    XGetInputFocus(fl_get_display(), &fb->save_window, &tmp);
+    XFlush(fl_get_display());
+
+    fl_show_form(fb->form, FL_PLACE_POSITION, FL_NOBORDER, "");
+
+    fl_select_browser_line(fb->browser, pos);
+    fl_set_browser_topline(fb->browser, pos);
+
+    XGrabPointer(fl_get_display(), fb->form->window, 0,
+                ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+                GrabModeAsync, GrabModeAsync,
+                0, 0, 0);
+    XFlush(fl_get_display());
+
+    fl_hide_tooltip();
+}
+
+
+void fl_hide_freebrowser(FL_FREEBROWSER * fb)
+{
+    XUngrabPointer(fl_get_display(), 0);
+    XFlush(fl_get_display());
+
+    if (fb->form->visible)
+       fl_hide_form(fb->form);
+
+    XSetInputFocus(fl_get_display(), fb->save_window,
+                  RevertToParent, CurrentTime);
+    XFlush(fl_get_display());
+
+    if (fb->callback)
+       fb->callback(fb, 0);
+}
+
+
+FL_OBJECT * fl_get_freebrowser_browser(FL_FREEBROWSER * fb)
+{
+    return fb->browser;
+}
+
+
+static void browser_cb(FL_OBJECT * ob, long data)
+{
+    FL_FREEBROWSER * fb = ob->u_vdata;
+    fl_hide_freebrowser(fb);
+    if (fb->callback)
+       fb->callback(fb, 1);
+}
+
+
+static int peek_event(FL_FORM * form, void * ev)
+{
+    XEvent * xev = ev;
+    FL_FREEBROWSER * fb = form->u_vdata;
+    FL_OBJECT * browser = fb->browser;
+
+    fb->last_printable = 0;
+    fl_hide_tooltip();
+
+    if (xev->type == ButtonPress &&
+       ((int)(xev->xbutton.x) - (int)(browser->x) < 0 ||
+        (int)(xev->xbutton.x) - (int)(browser->x) > (int)(browser->w) ||
+        (int)(xev->xbutton.y) - (int)(browser->y) < 0 ||
+        (int)(xev->xbutton.y) - (int)(browser->y) > (int)(browser->h))) {
+       fl_hide_freebrowser(fb);
+       return 1;
+    }
+
+    if (xev->type == KeyPress) {
+       char s_r[10]; s_r[9] = '\0';
+       KeySym keysym_return;
+       XLookupString(&xev->xkey, s_r, 10, &keysym_return, 0);
+
+       XFlush(fl_get_display());
+
+       switch (keysym_return) {
+       case XK_Down:
+#ifdef XK_KP_Down
+       case XK_KP_Down:
+#endif
+       {
+           int sel = fl_get_browser(browser);
+           int const top = fl_get_browser_topline(browser);
+           int const screenlines = fl_get_browser_screenlines(browser);
+
+           if (sel < 1 || sel >= fl_get_browser_maxline(browser))
+               return 0;
+
+           ++sel;
+           fl_select_browser_line(browser, sel);
+
+           if (sel >= top + screenlines)
+               fl_set_browser_topline(browser, sel - screenlines + 1);
+
+           if (sel < top)
+               fl_set_browser_topline(browser, sel);
+
+           return 1;
+       }
+
+       case XK_Up:
+#ifdef XK_KP_Up
+       case XK_KP_Up:
+#endif
+       {
+           int sel = fl_get_browser(browser);
+           int const top = fl_get_browser_topline(browser);
+           int const screenlines = fl_get_browser_screenlines(browser);
+
+           if (sel <= 1 || sel > fl_get_browser_maxline(browser))
+               return 0;
+
+           --sel;
+           fl_select_browser_line(browser, sel);
+
+           if (sel >= top + screenlines)
+               fl_set_browser_topline(browser, sel - screenlines + 1);
+
+           if (sel < top)
+               fl_set_browser_topline(browser, sel);
+
+           return 1;
+       }
+
+       case XK_Return:
+#ifdef XK_KP_Enter
+       case XK_KP_Enter:
+#endif
+           fl_hide_freebrowser(fb);
+           if (fb->callback)
+               fb->callback(fb, 1);
+           return 1;
+
+       case XK_Escape:
+           fl_hide_freebrowser(fb);
+           return 1;
+       default:
+           if (fb->want_printable && s_r[0] && isprint(s_r[0])) {
+               fb->last_printable = s_r[0];
+               fl_hide_freebrowser(fb);
+               if (fb->callback)
+                   fb->callback(fb, 1);
+               return 1;
+           }
+       }
+    }
+    return 0;
+}
diff --git a/src/frontends/xforms/freebrowser.h b/src/frontends/xforms/freebrowser.h
new file mode 100644 (file)
index 0000000..a7d7a72
--- /dev/null
@@ -0,0 +1,68 @@
+/**
+ * \file freebrowser.h
+ * \author Angus Leeming
+ *
+ * A freebrowser is a browser widget in its own form.
+ * It is used for example to instantiate the drop-down list beneath a
+ * combox.
+ */
+
+#ifndef FL_FREEBROWSER_H
+#define FL_FREEBROWSER_H
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+enum freebrowser_position {
+    FL_FREEBROWSER_BELOW,
+    FL_FREEBROWSER_ABOVE
+};
+
+typedef struct fl_freebrowser_ {
+    /** Use this and you'll be told when something happens.
+     * \param == 0: the browser has merely been hidden.
+     *         == 1: a change has been made.
+     */
+    void (* callback) (struct fl_freebrowser_ *, int action);
+
+    /** Set this to 1 if you want to capture all KeyPress events
+     *  generating printable chars.
+     */
+    int want_printable;
+    /** Is set only if want_printable is true. */
+    char last_printable;
+
+    /** Details of the implementation. */
+    void * parent;
+    FL_FORM * form;
+    FL_OBJECT * browser;
+    Window save_window;
+} FL_FREEBROWSER;
+
+
+/** A function to create a freebrowser widget, "owned" by widget \param parent.
+ */
+FL_EXPORT FL_FREEBROWSER * fl_create_freebrowser(void * parent);
+
+FL_EXPORT void fl_free_freebrowser(FL_FREEBROWSER *);
+
+/** \param abs_x, \param abs_y are the coordinates of the top left corner
+ *  of the browser relative to the top left hand corner of the _screen_.
+ *  \param w, \param h are the browser dimensions.
+ */
+FL_EXPORT void fl_show_freebrowser(FL_FREEBROWSER *,
+                                  FL_Coord abs_x, FL_Coord abs_y,
+                                  FL_Coord w, FL_Coord h);
+
+FL_EXPORT void fl_hide_freebrowser(FL_FREEBROWSER *);
+
+/** Return the browser itself. */
+FL_EXPORT FL_OBJECT * fl_get_freebrowser_browser(FL_FREEBROWSER *);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
index aceff7a8da213ff4a51df87a80f14048cb0a2228..1fe3d7bac36af3c6fae890f01bf066bd2de2bac7 100644 (file)
@@ -26,6 +26,7 @@
 #include <fstream>
 
 #include FORMS_H_LOCATION
+#include "combox.h"
 
 using std::ofstream;
 using std::pair;
@@ -131,6 +132,10 @@ string const getString(FL_OBJECT * ob, int line)
                        tmp = fl_get_choice_item_text(ob, line);
                break;
 
+       case FL_COMBOX:
+               tmp = fl_get_combox_text(ob);
+               break;
+
        default:
                lyx::Assert(0);
        }