]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/xforms/combox.C
fix crash with "save as"
[lyx.git] / src / frontends / xforms / combox.C
index 5edc3f6f03d2726b42927540911787759b915df9..6100cdf17e5bafab854e57832d335b49d543155d 100644 (file)
@@ -1,32 +1,36 @@
-/*
- *  Combox: A combination of two objects (a button and a browser) is
- *          encapsulated to get a combobox-like object. All XForms 
- *          functions are hidden.         
- * 
- *  GNU Copyleft 1996 Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
- *                        and the LyX Team.
- * 
- *  Dependencies:  Only XForms, but created to be used with LyX.
- * 
- */ 
+/**
+ * \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 
+ *
+ *  2/06/1996,   Alejandro Aguilar Sierra
  *    Created and tested.
- *  
- *  4/06/1996,   Alejandro Aguilar Sierra 
+ *
+ *  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 
+ *
+ *  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>
 
@@ -44,19 +48,19 @@ 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) 
+       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)
        {
@@ -67,7 +71,7 @@ extern "C" {
 
 
 Combox::Combox(combox_type t)
-       : type(t), tabfolder1(0), tabfolder2(0)
+       : type(t)
 {
    browser = button = 0;
    callback = 0;
@@ -82,13 +86,14 @@ Combox::Combox(combox_type t)
 
 Combox::~Combox()
 {
-   remove();
+       // This is now handled by the XFormsView destructor (Lgb)
+       // remove();
 }
 
 
 void Combox::clear()
 {
-       if (browser) fl_clear_browser(browser);   
+       if (browser) fl_clear_browser(browser);
        sel = 0;
        if (type == FL_COMBOX_INPUT)
                fl_set_input(label, "");
@@ -103,15 +108,15 @@ void Combox::remove()
        lyxerr[Debug::GUI] << "Button: " << button << endl;
        if (button) {
                fl_delete_object(button);
-               fl_free_object(button); 
+               fl_free_object(button);
        }
-       
+
        lyxerr[Debug::GUI] << "Label: " << label << endl;
        if (label && label != button) {
                fl_delete_object(label);
-               fl_free_object(label); 
+               fl_free_object(label);
        }
-       
+
        lyxerr[Debug::GUI] << "Form: " << form << endl;
        lyxerr[Debug::GUI] << "Browser: " << browser << endl;
        if (form && browser) {
@@ -119,8 +124,8 @@ void Combox::remove()
           fl_free_object(browser);
           fl_free_form(form);
        }
-       button = 0; 
-       browser = 0; 
+       button = 0;
+       browser = 0;
        label = 0;
        form = 0;
        sel = 0;
@@ -132,14 +137,14 @@ 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()); 
+                       fl_set_object_label(label, text.c_str());
        }
        is_empty = false;
 }
@@ -149,7 +154,7 @@ 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);
@@ -163,26 +168,21 @@ bool Combox::select(string const & t)
 void Combox::select(int i)
 {
        if (!browser || !button) return;
-       if (i > 0 && i <= fl_get_browser_maxline(browser)) sel = i; 
+       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); 
+               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 * tabfolder1_, FL_OBJECT * tabfolder2_)
+void Combox::add(int x, int y, int w, int hmin, int hmax)
 {
-       // Store these for later use in working round an xforms bug in show()
-       tabfolder1 = tabfolder1_;
-       tabfolder2 = tabfolder2_;
-
        FL_OBJECT * obj;
-       
+
        switch (type) {
        case FL_COMBOX_DROPLIST:
        {
@@ -191,7 +191,7 @@ void Combox::add(int x, int y, int w, int hmin, int hmax,
                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, "");
+               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);
@@ -235,7 +235,8 @@ void Combox::add(int x, int y, int w, int hmin, int hmax,
        FL_FORM * current_form = fl_current_form;
        fl_end_form();
 
-       bw = w + 20; bh = hmax - hmin - 12;
+       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, "");
@@ -246,7 +247,7 @@ void Combox::add(int x, int y, int w, int hmin, int hmax,
        fl_end_form();
        browser->u_vdata = this;
        form->u_vdata = browser;
-       fl_register_raw_callback(form, 
+       fl_register_raw_callback(form,
                                 ButtonPressMask|KeyPressMask,
                                 C_Combox_peek_event);
 
@@ -268,52 +269,36 @@ void Combox::redraw()
        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_set_object_label(button, "@2<-");
                fl_redraw_object(button);
        }
 
-       int x = label->x;
-       int y = label->y + label->h;
-       if (tabfolder1) {
-               // This is a bug work around suggested by Steve Lamont on the
-               // xforms mailing list. It correctly positions the browser form
-               // after the main window has been moved.
-               // The bug only occurs in tabbed folders.
-               int folder_x, folder_y, folder_w, folder_h;
-               fl_get_folder_area( tabfolder1,
-                                   &folder_x, &folder_y,
-                                   &folder_w, &folder_h );
-               x += folder_x;
-               y += folder_y;
-
-               if (tabfolder2) {
-                       fl_get_folder_area( tabfolder2,
-                                           &folder_x, &folder_y,
-                                           &folder_w, &folder_h );
-                       x += tabfolder2->form->x + folder_x;
-                       y += tabfolder2->form->y + folder_y;
-               } else {
-                       x += tabfolder1->form->x;
-                       y += tabfolder1->form->y;
-               }
-               
-       } else {
-               x += label->form->x;
-               y += label->form->y;
+       // This fix ensures that, even if label lies on a tabfolder,
+       // the x,y coords of the underlying form are up to date.
+       // It should be rendered redundant by a similar fix in the
+       // tabfolder prehandler, but apparently "enter" events are not always
+       // caught...
+       // Angus 4 Oct, 2002.
+       if (label->form->window) {
+               FL_FORM * lf = label->form;
+               fl_get_winorigin(lf->window, &(lf->x), &(lf->y));
        }
 
+       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) {
+       if (sel > 0) {
                fl_set_browser_topline(browser, sel);
                fl_select_browser_line(browser, sel);
        }
@@ -325,50 +310,64 @@ void Combox::show()
 }
 
 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));         
+                                           fl_get_browser_line(browser, sel));
 //             if (callback) callback(sel, cb_arg);
        }
-        XUngrabPointer(fl_get_display(), 0);
+       XUngrabPointer(fl_get_display(), 0);
        XFlush(fl_get_display());
-        if (form) {
+       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){
+               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();
+       if (_post) _post();
 }
 
 
 void Combox::activate()
 {
-       if (browser) fl_activate_object(browser);
-       if (button) fl_activate_object(button);
-       if (label) fl_activate_object(label);
+       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);
-       if (label) fl_deactivate_object(label);
+       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);
+       }
 }
 
 
@@ -388,20 +387,20 @@ 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: 
+               case 2:
                {
-                       combo->select(i - 1); 
+                       combo->select(i - 1);
                        if (combo->callback)
                                combo->callback(combo->sel,
                                                combo->cb_arg, combo);
                        break;
                }
-               case 3: 
+               case 3:
                {
-                       combo->select(i + 1);  
+                       combo->select(i + 1);
                        if (combo->callback)
                                combo->callback(combo->sel,
                                                combo->cb_arg, combo);
@@ -422,31 +421,34 @@ 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 
+
+       // 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); 
+               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, 
+       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)>= 
+               if (fl_get_browser(combo->browser)>=
                    fl_get_browser_topline(combo->browser) +
                    fl_get_browser_screenlines(combo->browser))
                        fl_set_browser_topline(combo->browser,
@@ -456,12 +458,15 @@ int Combox::peek_event(FL_FORM * form, void * xev)
                    fl_get_browser_topline(combo->browser))
                        fl_set_browser_topline(combo->browser,
                                               fl_get_browser(combo->browser));
-               return 1; 
+               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)>= 
+               if (fl_get_browser(combo->browser)>=
                    fl_get_browser_topline(combo->browser) +
                    fl_get_browser_screenlines(combo->browser))
                        fl_set_browser_topline(combo->browser,
@@ -473,13 +478,16 @@ int Combox::peek_event(FL_FORM * form, void * xev)
                                               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;  
+       return 0;
 }
 
 
@@ -495,17 +503,17 @@ typedef struct {
 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); 
+   combo.add(10, 15, 120, 25, 135);
    fl_end_form();
 
   return fdui;
@@ -519,8 +527,8 @@ void combo_cb(int i)
 int main(int argc, char *argv[])
 {
        //int n1;
-   
-   // Same defaults as in lyx 
+
+   // Same defaults as in lyx
    FL_IOPT cntl;
    cntl.buttonFontSize = FL_NORMAL_SIZE;
    cntl.browserFontSize = FL_NORMAL_SIZE;
@@ -528,14 +536,14 @@ int main(int argc, char *argv[])
    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_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 */
@@ -552,7 +560,7 @@ int main(int argc, char *argv[])
    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();