3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Alejandro Aguilar Sierra
7 * \author Lars Gullik Bjønnes
8 * \author Jean-Marc Lasgouttes
9 * \author Angus Leeming
11 * Full author contact details are available in file CREDITS
13 * This is a rewrite of Alejandro's C++ Combox class, originally written
14 * for LyX in 1996. The rewrite turns it into a native xforms widget.
18 #include "lyx_forms.h"
19 #include "freebrowser.h"
20 #include <ctype.h> /* isprint */
22 extern void fl_hide_tooltip(void);
24 static void browser_cb(FL_OBJECT * ob, long data);
25 static int peek_event(FL_FORM * form, void * xev);
29 fl_create_freebrowser(void * parent)
31 FL_FORM * current_form = fl_current_form;
32 FL_FREEBROWSER * fb = fl_calloc(1, sizeof(FL_FREEBROWSER));
36 FL_Coord const w = 100;
37 FL_Coord const h = 100;
41 fb->want_printable = 0;
42 fb->last_printable = 0;
44 if (current_form) fl_end_form();
45 fb->form = fl_bgn_form(FL_NO_BOX, w, h);
47 fb->form->u_vdata = fb;
48 fl_register_raw_callback(fb->form, ButtonPressMask|KeyPressMask,
51 ob = fb->browser = fl_add_browser(FL_HOLD_BROWSER, 0, 0, w, h, "");
53 fl_set_object_boxtype(ob, FL_UP_BOX);
54 fl_set_object_color(ob, FL_MCOL, FL_YELLOW);
55 fl_set_object_gravity(ob, NorthWestGravity, SouthEastGravity);
56 fl_set_object_callback(ob, browser_cb, 0);
60 fl_addto_form(current_form);
67 fl_free_freebrowser(FL_FREEBROWSER * fb)
73 fl_free_form(fb->form);
81 fl_show_freebrowser(FL_FREEBROWSER * fb,
82 FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h)
85 int const pos = fl_get_browser(fb->browser);
87 fl_set_form_geometry(fb->form, x, y, w, h);
89 XGetInputFocus(fl_get_display(), &fb->save_window, &tmp);
90 XFlush(fl_get_display());
92 fl_show_form(fb->form, FL_PLACE_POSITION, FL_NOBORDER, "");
94 fl_select_browser_line(fb->browser, pos);
95 fl_set_browser_topline(fb->browser, pos);
97 XGrabPointer(fl_get_display(), fb->form->window, 0,
98 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
99 GrabModeAsync, GrabModeAsync,
101 XFlush(fl_get_display());
108 fl_hide_freebrowser(FL_FREEBROWSER * fb)
110 XUngrabPointer(fl_get_display(), 0);
111 XFlush(fl_get_display());
113 if (fb->form->visible)
114 fl_hide_form(fb->form);
116 XSetInputFocus(fl_get_display(), fb->save_window,
117 RevertToParent, CurrentTime);
118 XFlush(fl_get_display());
126 browser_cb(FL_OBJECT * ob, long data)
128 FL_FREEBROWSER * fb = ob->u_vdata;
129 fl_hide_freebrowser(fb);
136 eventWithinObj(XEvent * xev, FL_OBJECT * ob)
140 int const xev_x = (int)(xev->xbutton.x);
141 int const xev_y = (int)(xev->xbutton.y);
142 int const ob_x = (int)(ob->x);
143 int const ob_y = (int)(ob->y);
144 int const ob_w = (int)(ob->w);
145 int const ob_h = (int)(ob->h);
147 int const dx = xev_x - ob_x;
148 int const dy = xev_y - ob_y;
150 /* result is true if the event occurred within the ob */
151 result = !(dx < 0 || dx > ob_w || dy < 0 || dy > ob_h);
158 peek_event(FL_FORM * form, void * ev)
161 FL_FREEBROWSER * fb = form->u_vdata;
162 FL_OBJECT * browser = fb->browser;
164 fb->last_printable = 0;
167 if (xev->type == ButtonPress && !eventWithinObj(xev, browser)) {
168 fl_hide_freebrowser(fb);
172 if (xev->type == KeyPress) {
173 KeySym keysym_return;
176 XLookupString(&xev->xkey, s_r, 10, &keysym_return, 0);
178 XFlush(fl_get_display());
180 switch (keysym_return) {
186 int sel = fl_get_browser(browser);
187 int const top = fl_get_browser_topline(browser);
188 int const screenlines = fl_get_browser_screenlines(browser);
190 if (sel < 1 || sel >= fl_get_browser_maxline(browser))
194 fl_select_browser_line(browser, sel);
196 if (sel >= top + screenlines)
197 fl_set_browser_topline(browser, sel - screenlines + 1);
200 fl_set_browser_topline(browser, sel);
210 int sel = fl_get_browser(browser);
211 int const top = fl_get_browser_topline(browser);
212 int const screenlines = fl_get_browser_screenlines(browser);
214 if (sel <= 1 || sel > fl_get_browser_maxline(browser))
218 fl_select_browser_line(browser, sel);
220 if (sel >= top + screenlines)
221 fl_set_browser_topline(browser, sel - screenlines + 1);
224 fl_set_browser_topline(browser, sel);
233 fl_hide_freebrowser(fb);
239 fl_hide_freebrowser(fb);
242 if (fb->want_printable && s_r[0] && isprint(s_r[0])) {
243 fb->last_printable = s_r[0];
244 fl_hide_freebrowser(fb);