]> git.lyx.org Git - features.git/blob - src/frontends/xforms/FormMaths.C
Compile fixes for DEC cxx, John's maths and keymap patches.
[features.git] / src / frontends / xforms / FormMaths.C
1 /**
2  * \file FormMaths.C
3  * Copyright 2001 The LyX Team.
4  * See the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  * \author Pablo De Napoli, pdenapo@dm.uba.ar
8  * \author John Levon, moz@compsoc.man.ac.uk
9  */
10
11 #include <config.h>
12
13 #ifdef __GNUG_
14 #pragma implementation
15 #endif
16
17 #include FORMS_H_LOCATION
18
19 #include "support/LAssert.h"
20 #include "FormMaths.h"
21 #include "form_maths.h"
22 #include "MathsSymbols.h"
23 #include "Dialogs.h"
24 #include "LyXView.h"
25 #include "lyxfunc.h"
26 #include "debug.h"
27 #include "bmtable.h"
28
29 #include "mathed/symbol_def.h"
30 #include "delim.xbm"
31 #include "delim0.xpm"
32 #include "delim.xpm"
33 #include "deco.xbm"
34 #include "deco.xpm"
35 #include "space.xpm"
36 #include "sqrt.xpm"
37 #include "frac.xpm"
38 #include "matrix.xpm"
39 #include "equation.xpm"
40 #include "greek.xbm"
41 #include "arrows.xbm"
42 #include "brel.xbm"
43 #include "bop.xbm"
44 #include "misc.xbm"
45 #include "varsz.xbm"
46 #include "dots.xbm"
47
48 using std::endl;
49 using SigC::slot;
50
51 static int const delim_rversion[] = { 
52         1,1,3,3,4,5,7,7,9,9,10,11,
53         13,13,14,15,16,17,19,19,20,21,22,23 };
54  
55 static char const * function_names[] = {
56         "arccos", "arcsin", "arctan", "arg", "bmod",
57         "cos", "cosh", "cot", "coth", "csc", "deg",
58         "det", "dim", "exp", "gcd", "hom", "inf", "ker",
59         "lg", "lim", "liminf", "limsup", "ln", "log",
60         "max", "min", "sec", "sin", "sinh", "sup",
61         "tan", "tanh"
62 };
63
64 static int const nr_function_names = sizeof(function_names) / sizeof(char const *);
65
66 static char const * decoration_names[] = {
67         "widehat", "widetilde", "overbrace", "overleftarrow", "overrightarrow", 
68         "overline", "underbrace", "underline"
69 };
70
71 static int const nr_decoration_names = sizeof(decoration_names) / sizeof(char const *);
72  
73 static int delim_values[] = {
74         '(', ')', LM_lceil,  LM_rceil,  LM_uparrow,  LM_Uparrow,
75         '[', ']', LM_lfloor,  LM_rfloor,  LM_updownarrow, LM_Updownarrow,
76         '{', '}',  '/', LM_backslash,  LM_downarrow,  LM_Downarrow,
77         LM_langle,  LM_rangle, '|', LM_Vert, '.', 0
78 };
79
80 extern "C" int C_FormMathsWMHideCB(FL_FORM * ob, void *)
81 {
82         fl_hide_form(ob);
83         return FL_CANCEL; 
84 }
85
86  
87 extern "C" void C_FormMathsButtonCB(FL_OBJECT * ob, long data)
88 {
89         FormMaths * form = static_cast<FormMaths*>(ob->form->u_vdata);
90         MathsCallbackValues val = static_cast<MathsCallbackValues>(data);
91
92         lyxerr[Debug::GUI] << "Maths button CB val " << val << endl;
93
94         switch (val) {
95                 case MM_GREEK:
96                 case MM_ARROW:
97                 case MM_BOP:
98                 case MM_BRELATS:
99                 case MM_VARSIZE:
100                 case MM_MISC:
101                         form->openBitmapMenu(val);
102                         break;
103
104                 case MM_FRAC:
105                         form->insertSymbol("frac");
106                         break;
107                 case MM_SQRT:
108                         form->insertSymbol("sqrt");
109                         break;
110
111                 case MM_DELIM:
112                 case MM_MATRIX:
113                 case MM_DECO:
114                 case MM_SPACE:
115                         form->openSubDialog(val);
116                         break;
117
118                 case MM_EQU:
119                         form->mathDisplay();
120                         break;
121
122                 case MM_FUNC:
123                         form->insertFunction();
124                         break;
125
126                 case MM_MAX:
127                 case MM_CLOSE:
128                 case MM_APPLY:
129                 case MM_OK:
130                         Assert(false);
131                         break;
132         }
133 }
134
135
136 extern "C" void C_FormMathsDelimCB(FL_OBJECT * ob, long data)
137 {
138         FormMaths * form = static_cast<FormMaths*>(ob->form->u_vdata);
139         MathsCallbackValues val = static_cast<MathsCallbackValues>(data);
140
141         lyxerr[Debug::GUI] << "Maths delim CB val " << val << endl;
142
143         int left = form->delim_->radio_left->u_ldata;
144         int right= form->delim_->radio_right->u_ldata;
145         int const side = (fl_get_button(form->delim_->radio_right) != 0);
146         std::ostringstream ost;
147  
148         ost << delim_values[left] << ' ' << delim_values[right];
149  
150         switch (val) {
151                 case MM_OK:
152                         form->insertDelim(ost.str());
153                 case MM_CLOSE:
154                         fl_hide_form(form->delim_->form);
155                         break;
156
157                 case MM_APPLY:
158                         form->insertDelim(ost.str());
159                         break;
160
161                 /* the bmtable */
162                 case 2: {
163                         int const i = fl_get_bmtable(form->delim_->bmtable_delim);
164                         int const button = fl_get_bmtable_numb(form->delim_->bmtable_delim);
165                         bool const both = (button == FL_MIDDLE_MOUSE);
166         
167                         if (i>= 0) {
168                                 if (side || (button == FL_RIGHT_MOUSE))
169                                         right = i;
170                                 else {
171                                         left = i;
172                                         if (both)
173                                                 right = delim_rversion[i];
174                                 }
175                         }
176  
177                         Pixmap p1, p2;
178  
179                         p1 = fl_get_pixmap_pixmap(form->delim_->button_delim_pix, &p1, &p2);
180                         fl_draw_bmtable_item(form->delim_->bmtable_delim, left, p1, 0, 0);
181                         fl_draw_bmtable_item(form->delim_->bmtable_delim, right, p1, 16, 0);
182                         fl_redraw_object(form->delim_->button_delim_pix);
183         
184                         form->delim_->radio_left->u_ldata = left;
185                         form->delim_->radio_right->u_ldata = right;
186                         } break;
187  
188                 /* left/right - ignore */
189                 case 3:
190                 case 4:
191                         break;
192  
193                 default:
194                         Assert(false);
195                         break;
196         }
197 }
198
199
200 extern "C" int align_filter(FL_OBJECT * ob, char const *, char const * cur, int c)
201 {
202         FormMaths * form = static_cast<FormMaths*>(ob->u_vdata);
203  
204         int n = int(fl_get_slider_value(form->matrix_->slider_matrix_columns)+0.5) - strlen(cur);
205         if (n < 0)
206                 return FL_INVALID;
207
208         if (c == 'c' || c == 'l' || c == 'r') 
209                 return FL_VALID;
210  
211         return FL_INVALID;
212 }
213  
214  
215 static char h_align_str[80] = "c";
216 static char v_align_c[] = "tcb";
217  
218 extern "C" void C_FormMathsMatrixCB(FL_OBJECT * ob, long data)
219 {
220  
221         FormMaths * form = static_cast<FormMaths*>(ob->form->u_vdata);
222         MathsCallbackValues val = static_cast<MathsCallbackValues>(data);
223
224         lyxerr[Debug::GUI] << "Maths matrix CB val " << val << endl;
225
226         switch (val) {
227                 case MM_OK:
228                         form->insertMatrix();
229                 case MM_CLOSE:
230                         fl_hide_form(form->matrix_->form);
231                         break;
232
233                 case MM_APPLY:
234                         form->insertMatrix();
235                         break;
236
237                 /* rows slider etc.: ignore */
238                 case -1:
239                         break;
240  
241                 /* the "columns" slider */
242                 case 2: {
243                         int const nx = int(fl_get_slider_value(form->matrix_->slider_matrix_columns)+0.5);
244                         for (int i = 0; i < nx; ++i) 
245                                 h_align_str[i] = 'c';
246  
247                         h_align_str[nx] = '\0';
248
249                         fl_set_input(form->matrix_->input_matrix_halign, h_align_str);
250                         fl_redraw_object(form->matrix_->input_matrix_halign);
251                         } break;
252  
253                 default:
254                         Assert(false);
255                         break;
256         }
257 }
258
259
260 extern "C" void C_FormMathsDecoCB(FL_OBJECT * ob, long data)
261 {
262         FormMaths * form = static_cast<FormMaths*>(ob->form->u_vdata);
263         MathsCallbackValues val = static_cast<MathsCallbackValues>(data);
264
265         lyxerr[Debug::GUI] << "Maths deco CB val " << val << endl;
266
267         int const i = fl_get_bmtable(form->deco_->bmtable_deco);
268  
269         if (i >= nr_decoration_names)
270                 return;
271  
272         string const deco_str = decoration_names[i];
273  
274         switch (val) {
275                 case MM_OK:
276                         form->insertSymbol(deco_str);
277                 case MM_CLOSE:
278                         fl_hide_form(form->deco_->form);
279                         break;
280
281                 case MM_APPLY:
282                         form->insertSymbol(deco_str);
283                         break;
284
285                 default:
286                         Assert(false);
287                         break;
288         }
289 }
290
291
292 extern "C" void C_FormMathsSpaceCB(FL_OBJECT * ob, long data)
293 {
294         extern char * latex_mathspace[];
295         static short sp = -1;
296  
297         if (data >= 0 && data < 6) {
298                 sp = data;
299                 return;
300         }
301  
302         FormMaths * form = static_cast<FormMaths*>(ob->form->u_vdata);
303         MathsCallbackValues val = static_cast<MathsCallbackValues>(data);
304
305         lyxerr[Debug::GUI] << "Maths space CB val " << val << endl;
306
307         switch (val) {
308                 case MM_OK:
309                         if (sp > 0)
310                                 form->insertSymbol(latex_mathspace[sp]);
311                 case MM_CLOSE:
312                         fl_hide_form(form->space_->form);
313                         break;
314
315                 case MM_APPLY:
316                         if (sp > 0)
317                                 form->insertSymbol(latex_mathspace[sp]);
318                         break;
319
320                 default:
321                         Assert(false);
322                         break;
323         }
324 }
325
326
327 FormMaths::FormMaths(LyXView * lv, Dialogs * d)
328         : FormBaseBD(lv, d, _("Maths Symbols"))
329 {
330         d->showMathPanel.connect(slot(this, &FormMaths::show));
331 }
332
333
334 FL_FORM * FormMaths::form() const
335 {
336         if (dialog_.get())
337                 return dialog_->form;
338         return 0;
339 }
340
341
342 extern "C" int C_MathsSymbolsPeekCB(FL_FORM *, void *);
343  
344 void FormMaths::build()
345 {
346         dialog_.reset(build_panel());
347         delim_.reset(build_delim());
348         matrix_.reset(build_matrix());
349         deco_.reset(build_deco());
350         space_.reset(build_space());
351
352         fl_set_form_atclose(delim_->form, C_FormMathsWMHideCB, delim_.get());
353         fl_set_form_atclose(matrix_->form, C_FormMathsWMHideCB, matrix_.get());
354         fl_set_form_atclose(deco_->form, C_FormMathsWMHideCB, deco_.get());
355         fl_set_form_atclose(space_->form, C_FormMathsWMHideCB, space_.get());
356  
357         // work around dumb xforms sizing bug
358         minw_ = form()->w;
359         minh_ = form()->h;
360
361         fl_set_button(space_->radio_space_thin, 1);
362         fl_set_button(delim_->radio_left, 1);
363         fl_set_pixmap_data(delim_->button_delim_pix, const_cast<char**>(delim0));
364         delim_->radio_left->u_ldata = 0;
365         delim_->radio_right->u_ldata = 1;
366  
367         fl_set_bmtable_data(delim_->bmtable_delim, 6, 4, delim_width, delim_height, delim_bits);
368         fl_set_bmtable_maxitems(delim_->bmtable_delim, 23);
369         
370         for (int i = 0; i < nr_function_names; ++i)
371                 fl_add_browser_line(dialog_->browser_functions, function_names[i]);
372         
373         fl_set_pixmap_data(dialog_->button_sqrt, const_cast<char**>(sqrt_xpm));
374         fl_set_pixmap_data(dialog_->button_frac, const_cast<char**>(frac));
375         fl_set_pixmap_data(dialog_->button_delim, const_cast<char**>(delim));
376         fl_set_pixmap_data(dialog_->button_deco, const_cast<char**>(deco));
377         fl_set_pixmap_data(dialog_->button_space, const_cast<char**>(space_xpm));
378         fl_set_pixmap_data(dialog_->button_matrix, const_cast<char**>(matrix));
379         fl_set_pixmap_data(dialog_->button_equation, const_cast<char**>(equation));
380         
381         fl_addto_choice(matrix_->choice_matrix_valign, _("Top | Center | Bottom"));
382         fl_set_choice(matrix_->choice_matrix_valign, 2);
383         fl_set_input(matrix_->input_matrix_halign, h_align_str);
384         matrix_->input_matrix_halign->u_vdata = this;
385         fl_set_input_filter(matrix_->input_matrix_halign, align_filter);
386         
387         fl_set_bmtable_data(deco_->bmtable_deco, 3, 3, deco_width, deco_height, deco_bits);
388         fl_set_bmtable_maxitems(deco_->bmtable_deco, 8);
389
390         build_symbol_menus();
391
392         // to close any bitmap menus on interacting with the main form
393         fl_register_raw_callback(dialog_->form, KeyPressMask|ButtonPressMask, C_MathsSymbolsPeekCB);
394  
395         bc_.setCancel(dialog_->button_close);
396         bc_.refresh();
397 }
398  
399
400 void FormMaths::build_symbol_menus()
401 {
402         FL_OBJECT * obj;
403
404         greek_.reset(new BitmapMenu(this, 2, dialog_->button_greek));
405         obj = greek_->AddBitmap(MM_GREEK, 6, 2,
406                                 Greek_width, Greek_height, Greek_bits);
407         fl_set_bmtable_maxitems(obj, 11);
408         obj = greek_->AddBitmap(MM_GREEK, 7, 4,
409                                 greek_width, greek_height, greek_bits);
410         greek_->create();
411
412         boperator_.reset(new BitmapMenu(this, 1, dialog_->button_boperator,
413                                         greek_.get()));
414         obj = boperator_->AddBitmap(MM_BOP, 4, 8,
415                                     bop_width, bop_height, bop_bits);
416         fl_set_bmtable_maxitems(obj, 31);
417         boperator_->create();
418
419         brelats_.reset(new BitmapMenu(this, 1, dialog_->button_brelats,
420                                       boperator_.get()));
421         obj = brelats_->AddBitmap(MM_BRELATS, 4, 9,
422                                   brel_width, brel_height, brel_bits);
423         fl_set_bmtable_maxitems(obj, 35);
424         brelats_->create();
425
426         arrow_.reset(new BitmapMenu(this, 3, dialog_->button_arrow,
427                                     brelats_.get()));
428         obj = arrow_->AddBitmap(MM_ARROW, 5, 4,
429                                 arrow_width, arrow_height, arrow_bits);
430         obj = arrow_->AddBitmap(MM_ARROW, 2, 4,
431                                 larrow_width, larrow_height, larrow_bits,
432                                 False);
433         fl_set_bmtable_maxitems(obj, 7);
434         obj = arrow_->AddBitmap(MM_ARROW, 2, 2,
435                                 darrow_width, darrow_height, darrow_bits);
436         arrow_->create();
437
438         varsize_.reset(new BitmapMenu(this, 1, dialog_->button_varsize,
439                                       arrow_.get()));
440         obj = varsize_->AddBitmap(MM_VARSIZE, 3, 5,
441                                   varsz_width, varsz_height, varsz_bits);
442         fl_set_bmtable_maxitems(obj, 14);
443         varsize_->create();
444
445         misc_.reset(new BitmapMenu(this, 2, dialog_->button_misc,
446                                    varsize_.get()));
447         obj = misc_->AddBitmap(MM_MISC, 5, 6,
448                                misc_width, misc_height, misc_bits);
449         fl_set_bmtable_maxitems(obj, 29);
450         obj = misc_->AddBitmap(MM_DOTS, 4, 1,
451                                dots_width, dots_height, dots_bits);
452         misc_->create();
453 }
454
455
456 void FormMaths::insertMatrix() const
457 {
458         char const c = v_align_c[fl_get_choice(matrix_->choice_matrix_valign) - 1];
459         char const * sh = fl_get_input(matrix_->input_matrix_halign);
460         int const nx = int(fl_get_slider_value(matrix_->slider_matrix_columns) + 0.5);
461         int const ny = int(fl_get_slider_value(matrix_->slider_matrix_rows) + 0.5);
462  
463         std::ostringstream ost;
464         ost << nx << ' ' << ny << ' ' << c << sh;
465  
466         lv_->getLyXFunc()->Dispatch(LFUN_INSERT_MATRIX, ost.str().c_str());
467 }
468
469  
470 void FormMaths::insertDelim(string const & delim) const
471 {
472         lv_->getLyXFunc()->Dispatch(LFUN_MATH_DELIM, delim);
473 }
474
475  
476 void FormMaths::openBitmapMenu(MathsCallbackValues val) const
477 {
478         switch (val) {
479                 case MM_GREEK:
480                         greek_->show();
481                         break;
482                 case MM_ARROW:
483                         arrow_->show();
484                         break;
485                 case MM_BOP:
486                         boperator_->show();
487                         break;
488                 case MM_BRELATS:
489                         brelats_->show();
490                         break;
491                 case MM_VARSIZE:
492                         varsize_->show();
493                         break;
494                 case MM_MISC:
495                         misc_->show();
496                         break;
497                 default:
498                         Assert(false);
499         }
500 }
501
502
503 void FormMaths::insertSymbol(string const & sym) const
504 {
505         lv_->getLyXFunc()->Dispatch(LFUN_INSERT_MATH, sym);
506 }
507
508
509 void FormMaths::mathDisplay() const
510 {
511         lv_->getLyXFunc()->Dispatch(LFUN_MATH_DISPLAY);
512 }
513
514
515 void FormMaths::openSubDialog(MathsCallbackValues val) const
516 {
517         FL_FORM * form = 0;
518         string title;
519
520         switch (val) {
521                 case MM_DELIM:
522                         form = delim_->form;
523                         title = "Delimiters";
524                         break;
525                 case MM_MATRIX:
526                         form = matrix_->form;
527                         title = "Matrix";
528                         break;
529                 case MM_DECO:
530                         form = deco_->form; 
531                         title = "Maths Decorations";
532                         break;
533                 case MM_SPACE:
534                         form = space_->form;
535                         title = "Maths Spacing";
536                         break;
537                 default:
538                         Assert(false);
539         }
540
541         if (form->visible) {
542                 fl_raise_form(form);
543                 XMapWindow(fl_get_display(), form->window);
544         } else
545                 fl_show_form(form, FL_PLACE_MOUSE | FL_FREE_SIZE, 0, title.c_str());
546 }
547
548
549 void FormMaths::insertFunction() const
550 {
551         int const i = fl_get_browser(dialog_->browser_functions) - 1;
552         insertSymbol(function_names[i]);
553 }