3 * Purpose: User interface to math symbols
4 * Author: Alejandro Aguilar Sierra <asierra@servidor.unam.mx>
5 * Created: November 1995
6 * Version: 0.8 28/03/96
7 * Description: Provides a GUI to introduce mathematical
10 * Dependencies: Xlib, XForms, Lyx
12 * Copyright: 1995, 1996, Alejandro Aguilar Sierra
14 * You are free to use and modify it under the terms of
15 * the GNU General Public Licence version 2 or later.
19 #include XPM_H_LOCATION
22 #pragma implementation "math_panel.h"
29 #include "BufferView.h"
30 #include "minibuffer.h"
33 #include "support/lstrings.h"
40 #include "math_panel.h"
41 #include "math_parser.h"
47 extern int greek_kb_flag;
49 extern BufferView * current_view;
60 /* Latex code for those bitmaps */
61 static char const * latex_greek[] = {
62 "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi",
63 "Sigma", "Upsilon", "Phi", "Psi", "Omega",
64 "alpha", "beta", "gamma", "delta", "epsilon", "varepsilon", "zeta",
65 "eta", "theta", "vartheta", "iota", "kappa", "lambda", "mu",
66 "nu", "xi", "pi", "varpi", "rho", "sigma", "varsigma",
67 "tau", "upsilon", "phi", "varphi", "chi", "psi", "omega", ""
70 static char const * latex_brel[] = {
71 "leq", "geq", "equiv", "models",
72 "prec", "succ", "sim", "perp",
73 "preceq", "succeq", "simeq", "mid",
74 "ll", "gg", "asymp", "parallel",
75 "subset", "supset", "approx", "smile",
76 "subseteq", "supseteq", "cong", "frown",
77 "sqsubseteq", "sqsupseteq", "doteq", "neq",
78 "in", "ni", "propto", "notin",
79 "vdash", "dashv", "bowtie", ""
82 static char const * latex_arrow[] = {
83 "downarrow", "leftarrow", "Downarrow", "Leftarrow",
84 "hookleftarrow", "rightarrow", "uparrow", "Rightarrow", "Uparrow",
85 "hookrightarrow", "updownarrow", "Leftrightarrow", "leftharpoonup",
86 "rightharpoonup", "rightleftharpoons", "leftrightarrow", "Updownarrow",
87 "leftharpoondown", "rightharpoondown", "mapsto",
88 "Longleftarrow", "Longrightarrow", "Longleftrightarrow",
89 "longleftrightarrow", "longleftarrow", "longrightarrow", "longmapsto",
90 "nwarrow", "nearrow", "swarrow", "searrow", "",
93 char const * latex_varsz[] = {
95 "prod", "coprod", "bigsqcup",
96 "bigotimes", "bigodot", "bigoplus",
97 "bigcap", "bigcup", "biguplus",
98 "bigvee", "bigwedge", ""
101 static char const * latex_bop[] = {
102 "pm", "cap", "diamond", "oplus",
103 "mp", "cup", "bigtriangleup", "ominus",
104 "times", "uplus", "bigtriangledown", "otimes",
105 "div", "sqcap", "triangleright", "oslash",
106 "cdot", "sqcup", "triangleleft", "odot",
107 "star", "vee", "amalg", "bigcirc",
108 "setminus", "wedge", "dagger", "circ",
109 "bullet", "wr", "ddagger", ""
112 static char const * latex_misc[] = {
113 "nabla", "partial", "infty", "prime", "ell",
114 "emptyset", "exists", "forall", "imath", "jmath",
115 "Re", "Im", "aleph", "wp", "hbar",
116 "angle", "top", "bot", "Vert", "neg",
117 "flat", "natural", "sharp", "surd", "triangle",
118 "diamondsuit", "heartsuit", "clubsuit", "spadesuit", ""
121 static char const * latex_dots[] = {
122 "ldots", "cdots", "vdots", "ddots"
125 extern char const ** mathed_get_pixmap_from_icon(int d);
126 extern "C" void math_cb(FL_OBJECT*, long);
127 static char const ** pixmapFromBitmapData(char const *, int, int);
128 void math_insert_symbol(char const * s);
129 bool math_insert_greek(char c);
131 BitmapMenu * BitmapMenu::active = 0;
133 BitmapMenu::BitmapMenu(int n, FL_OBJECT * bt, BitmapMenu * prevx)
134 : current_(0), bitmaps_(n)
138 ww = 2 * FL_abs(FL_BOUND_WIDTH);
142 button->u_vdata = this;
150 BitmapMenu::~BitmapMenu()
153 if (form->visible) Hide();
158 void BitmapMenu::Hide()
161 fl_set_button(button, 0);
166 void BitmapMenu::Show()
171 // int x = button->form->x + button->x, y = button->form->y + button->y;
172 // fl_set_form_position(form, x, y + button->h);
173 fl_set_button(button, 1);
174 fl_show_form(form, FL_PLACE_MOUSE, FL_NOBORDER, "");
178 BitmapMenu::AddBitmap(int id, int nx, int ny, int bw, int bh,
179 unsigned char const * data, Bool vert)
181 if (current_ >= bitmaps_.size())
183 int wx = bw+ww/2, wy = bh+ww/2;
186 FL_OBJECT * obj = fl_create_bmtable(1, x, y, wx, wy, "");
187 fl_set_object_callback(obj, math_cb, id);
188 fl_set_object_lcol(obj, FL_BLUE);
189 fl_set_object_boxtype(obj, FL_UP_BOX);
190 fl_set_bmtable_data(obj, nx, ny, bw, bh, data);
194 w = max(x + wx + ww, w);
198 h = max(y + wy + ww, h);
200 bitmaps_[current_++] = obj;
204 void BitmapMenu::Create()
206 if (current_ < bitmaps_.size()) {
207 lyxerr << "Error: Bitmaps not created!" << endl;
210 form = fl_bgn_form(FL_UP_BOX, w, h);
211 for (current_ = 0; current_ < bitmaps_.size(); ++current_) {
212 fl_add_object(form, bitmaps_[current_]);
213 bitmaps_[current_]->u_vdata = this;
216 fl_register_raw_callback(form, KeyPressMask, C_peek_event);
219 int BitmapMenu::GetIndex(FL_OBJECT* ob)
221 if (active == this) {
223 for (current_ = 0; current_ < bitmaps_.size(); ++current_) {
224 if (bitmaps_[current_] == ob)
225 return k+fl_get_bmtable(ob);
226 k += fl_get_bmtable_maxitems(bitmaps_[current_]);
232 int peek_event(FL_FORM * /*form*/, void *xev)
234 if (BitmapMenu::active == 0)
237 if (static_cast<XEvent *>(xev)->type == ButtonPress)
239 BitmapMenu::active->Hide();
242 if (static_cast<XEvent *>(xev)->type == KeyPress)
246 XLookupString(&static_cast<XEvent *>(xev)->xkey, &c[0], 5, &keysym, 0);
247 if (keysym == XK_Left)
248 BitmapMenu::active->Prev(); else
249 if (keysym == XK_Right)
250 BitmapMenu::active->Next();
252 BitmapMenu::active->Hide();
258 // This is just a wrapper.
259 extern "C" int C_peek_event(FL_FORM *form, void *ptr) {
260 return peek_event(form, ptr);
264 extern "C" void math_cb(FL_OBJECT* ob, long data)
266 BitmapMenu * menu = static_cast<BitmapMenu*>(ob->u_vdata);
267 int i = menu->GetIndex(ob);
270 // lyxerr << "data[" << data << "]";
292 // lyxerr << "dots[" << latex_dots[i] << " " << i << "]";
293 s = latex_dots[i-29];
298 if (current_view->available() && lyxrc.display_shortcuts) {
299 current_view->owner()->getMiniBuffer()->Set("Inserting symbol ", s);
301 current_view->owner()->getLyXFunc()->Dispatch(LFUN_INSERT_MATH, s);
307 char const ** get_pixmap_from_symbol(char const * arg, int wx, int hx)
309 char const ** data = 0;
310 latexkeys * l = in_word_set (arg, strlen(arg));
316 data = mathed_get_pixmap_from_icon(MM_FRAC);
319 data = mathed_get_pixmap_from_icon(MM_SQRT);
323 // I have to use directly the bitmap data since the
324 // bitmap tables are not yet created when this
325 // function is called.
326 data = pixmapFromBitmapData(arg, wx, hx);
333 bool math_insert_greek(BufferView * bv, char c)
335 if (bv->available() &&
336 (('A' <= c && c <= 'Z') ||
337 ('a'<= c && c<= 'z'))) {
340 if (!bv->theLockingInset() || bv->theLockingInset()->IsTextInset()) {
341 int greek_kb_flag_save = greek_kb_flag;
342 InsetFormula * new_inset = new InsetFormula();
343 bv->beforeChange(bv->text);
344 if (!bv->insertInset(new_inset)) {
349 new_inset->Edit(bv, 0, 0, 0);
350 new_inset->LocalDispatch(bv, LFUN_SELFINSERT, tmp);
351 if (greek_kb_flag_save < 2) {
352 bv->unlockInset(new_inset); // bv->theLockingInset());
353 bv->text->CursorRight(bv, true);
356 if (bv->theLockingInset()->LyxCode() == Inset::MATH_CODE ||
357 bv->theLockingInset()->LyxCode() == Inset::MATHMACRO_CODE)
358 static_cast<InsetFormula*>(bv->theLockingInset())->LocalDispatch(bv, LFUN_SELFINSERT, tmp);
360 lyxerr << "Math error: attempt to write on a wrong "
361 "class of inset." << endl;
368 void math_insert_symbol(BufferView * bv, string const & s)
370 if (bv->available()) {
371 if (!bv->theLockingInset() || bv->theLockingInset()->IsTextInset()) {
372 InsetFormula * new_inset = new InsetFormula();
373 bv->beforeChange(bv->text);
374 if (!bv->insertInset(new_inset)) {
379 new_inset->Edit(bv, 0, 0, 0);
380 new_inset->InsertSymbol(bv, s);
382 if (bv->theLockingInset()->LyxCode() == Inset::MATH_CODE ||
383 bv->theLockingInset()->LyxCode() == Inset::MATHMACRO_CODE)
384 static_cast<InsetFormula*>(bv->theLockingInset())->InsertSymbol(bv, s);
386 lyxerr << "Math error: attempt to write on a wrong "
387 "class of inset." << endl;
392 BitmapMenu * sym_menu= 0;
394 void create_symbol_menues(FD_panel * symb_form)
399 sym_menu = menu = new BitmapMenu(2, symb_form->greek);
400 obj = menu->AddBitmap(MM_GREEK, 6, 2, Greek_width, Greek_height,
402 fl_set_bmtable_maxitems(obj, 11);
403 obj = menu->AddBitmap(MM_GREEK, 7, 4, greek_width, greek_height,
407 menu = new BitmapMenu(1, symb_form->boperator, menu);
408 obj = menu->AddBitmap(MM_BOP, 4, 8, bop_width, bop_height,
410 fl_set_bmtable_maxitems(obj, 31);
413 menu = new BitmapMenu(1, symb_form->brelats, menu);
414 obj = menu->AddBitmap(MM_BRELATS, 4, 9, brel_width, brel_height,
416 fl_set_bmtable_maxitems(obj, 35);
419 menu = new BitmapMenu(3, symb_form->arrow, menu);
420 obj = menu->AddBitmap(MM_ARROW, 5, 4, arrow_width, arrow_height,
422 obj = menu->AddBitmap(MM_ARROW, 2, 4, larrow_width, larrow_height,
424 fl_set_bmtable_maxitems(obj, 7);
425 obj = menu->AddBitmap(MM_ARROW, 2, 2, darrow_width, darrow_height,
429 menu = new BitmapMenu(1, symb_form->varsize, menu);
430 obj = menu->AddBitmap(MM_VARSIZE, 3, 5, varsz_width, varsz_height,
432 fl_set_bmtable_maxitems(obj, 14);
435 menu = new BitmapMenu(2, symb_form->misc, menu);
436 obj = menu->AddBitmap(MM_MISC, 5, 6, misc_width, misc_height,
438 fl_set_bmtable_maxitems(obj, 29);
439 obj = menu->AddBitmap(MM_DOTS, 4, 1, dots_width, dots_height,
445 char const ** pixmapFromBitmapData(char const * s, int wx, int hx)
448 char const ** data = 0;
452 for (i = 0; i < 6; ++i) {
453 char const ** latex_str = 0;
455 case 0: latex_str = latex_greek; break;
456 case 1: latex_str = latex_bop; break;
457 case 2: latex_str = latex_brel; break;
458 case 3: latex_str = latex_arrow; break;
459 case 4: latex_str = latex_varsz; break;
460 case 5: latex_str = latex_misc; break;
463 for (int k = 0; latex_str[k][0] > ' '; ++k) {
464 if (strcmp(latex_str[k], s) == 0) {
471 if (i < 6 && id >= 0) {
472 unsigned char const * bdata = 0;
473 int w = 0, h = 0, dw = 0, dh = 0;
475 lyxerr[Debug::MATHED] << "Imando " << i << ", " << id << endl;
536 int ww = w/dw, hh = h/dh, x, y;
538 XImage * xima = XCreateImage(fl_get_display(), 0, 1, XYBitmap, 0,
539 const_cast<char*>(reinterpret_cast<char const *>(bdata)), w, h, 8, 0);
540 xima->byte_order = LSBFirst;
541 xima->bitmap_bit_order = LSBFirst;
544 if (ww > wx) ww = wx;
545 if (hh > hx) hh = hx;
546 XImage * sbima = XSubImage(xima, x, y, ww, hh);
547 XpmCreateDataFromImage(fl_get_display(), const_cast<char***>(&data), sbima, sbima, 0);
549 // Dirty hack to get blue symbols quickly
550 char * sx = const_cast<char*>(strstr(data[2], "FFFFFFFF"));
552 for (int k = 0; k < 8; ++k) sx[k] = '0';
555 // XDestroyImage(xima);