]> git.lyx.org Git - lyx.git/blob - src/mathed/math_symbols.C
fix crossref label list, some debug messages + various
[lyx.git] / src / mathed / math_symbols.C
1 /*
2  *  File:        math_symbols.C
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
8  *               symbols in lyx.
9  *
10  *  Dependencies: Xlib, XForms, Lyx
11  *
12  *  Copyright: (c) 1995, 1996, Alejandro Aguilar Sierra 
13  *
14  *   You are free to use and modify it under the terms of
15  *   the GNU General Public Licence version 2 or later.
16  */
17
18 #include <config.h>
19 #include XPM_H_LOCATION
20
21 #ifdef __GNUG__
22 #pragma implementation "math_panel.h"
23 #endif
24
25 #include <algorithm>
26 using std::max;
27
28 #include "lyx_main.h"
29 #include "buffer.h"
30 #include "BufferView.h"
31 #include "minibuffer.h"
32 #include "lyxrc.h"
33 #include "LyXView.h"
34 #include "support/lstrings.h"
35 #include "debug.h"
36
37 #include "formula.h"
38
39 #include "math_panel.h"                 
40 #include "math_parser.h"
41
42 //extern void Update(signed char);
43 //extern int UnlockInset(UpdatableInset *);
44 extern short greek_kb_flag;
45
46 extern BufferView * current_view;
47
48 /* Bitmaps */
49 #include "greek.xbm"
50 #include "arrows.xbm"
51 #include "brel.xbm"
52 #include "bop.xbm"
53 #include "misc.xbm"           
54 #include "varsz.xbm"           
55 #include "dots.xbm"
56
57 /* Latex code for those bitmaps */
58 static char const * latex_greek[] =  {
59    "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi",
60    "Sigma", "Upsilon", "Phi", "Psi", "Omega",
61    "alpha", "beta", "gamma", "delta", "epsilon", "varepsilon", "zeta",
62    "eta", "theta", "vartheta", "iota", "kappa", "lambda", "mu",
63    "nu", "xi", "pi", "varpi", "rho", "sigma", "varsigma",
64    "tau", "upsilon", "phi", "varphi", "chi", "psi", "omega", ""
65 };
66
67 static char const * latex_brel[] = {
68   "leq", "geq", "equiv", "models", 
69   "prec", "succ", "sim", "perp", 
70   "preceq", "succeq", "simeq", "mid", 
71   "ll", "gg", "asymp", "parallel", 
72   "subset", "supset", "approx", "smile", 
73   "subseteq", "supseteq", "cong", "frown", 
74   "sqsubseteq", "sqsupseteq", "doteq", "neq", 
75   "in", "ni", "propto", "notin", 
76   "vdash", "dashv", "bowtie", ""
77 };
78
79 static char const * latex_arrow[] = {
80   "downarrow", "leftarrow", "Downarrow", "Leftarrow", 
81   "hookleftarrow", "rightarrow", "uparrow", "Rightarrow", "Uparrow",
82   "hookrightarrow", "updownarrow", "Leftrightarrow", "leftharpoonup", 
83   "rightharpoonup", "rightleftharpoons", "leftrightarrow", "Updownarrow", 
84   "leftharpoondown", "rightharpoondown", "mapsto",
85   "Longleftarrow", "Longrightarrow", "Longleftrightarrow", 
86   "longleftrightarrow", "longleftarrow", "longrightarrow", "longmapsto",
87   "nwarrow", "nearrow", "swarrow", "searrow",  "",
88 };
89
90 char const * latex_varsz[] = {
91 "sum", "int", "oint", 
92 "prod", "coprod", "bigsqcup", 
93 "bigotimes", "bigodot", "bigoplus", 
94 "bigcap", "bigcup", "biguplus", 
95 "bigvee", "bigwedge", ""
96 };
97
98 static char const * latex_bop[] = {   
99   "pm", "cap", "diamond", "oplus", 
100   "mp", "cup", "bigtriangleup", "ominus", 
101   "times", "uplus", "bigtriangledown", "otimes", 
102   "div", "sqcap", "triangleright", "oslash", 
103   "cdot", "sqcup", "triangleleft", "odot", 
104   "star", "vee", "amalg", "bigcirc", 
105   "setminus", "wedge", "dagger", "circ", 
106   "bullet", "wr", "ddagger", ""
107 };
108
109 static char const * latex_misc[] = {
110   "nabla", "partial", "infty", "prime", "ell", 
111   "emptyset", "exists", "forall", "imath",  "jmath",
112   "Re", "Im", "aleph", "wp", "hbar", 
113   "angle", "top", "bot", "Vert", "neg", 
114   "flat", "natural", "sharp", "surd", "triangle", 
115   "diamondsuit", "heartsuit", "clubsuit", "spadesuit", "" 
116 };
117
118 static char const * latex_dots[] = { 
119    "ldots", "cdots", "vdots", "ddots"
120 };
121
122 static signed char latin2greek[] =  {
123   0, 1, 25, 3, 4, 23, 2, 7, 10, 24, 11, 12, 13, 14, -1, 16, 8, 18,
124   19, 21, 22, 17, 27, 15, 26, 6
125 };
126  
127 static signed char Latin2Greek[] =  {
128  -1, -1, -1, 1, -1, 8, 0, -1, -1, -1, -1, 3, -1, -1, -1,
129  5, 2, -1, 6, -1, 7, -1, 10, 4, 9, -1
130 }; 
131
132 extern char const ** mathed_get_pixmap_from_icon(int d);
133 extern "C" void math_cb(FL_OBJECT*, long);
134 static char const ** pixmapFromBitmapData(char const *, int, int);
135 void math_insert_symbol(char const * s);
136 Bool math_insert_greek(char const c);
137
138 BitmapMenu * BitmapMenu::active = 0;
139
140 BitmapMenu::BitmapMenu(int n,  FL_OBJECT * bt, BitmapMenu * prevx): nb(n)
141 {
142    w = h = 0;
143    form = 0;
144    i = 0;
145    ww = 2 * FL_abs(FL_BOUND_WIDTH);
146    x = y = ww;
147    y += 8;
148    bitmap = new FL_OBJECTP[nb];
149    button = bt;
150    button->u_vdata = this;
151    prev = prevx;
152    next = 0;
153    if (prev)
154      prev->next = this;
155 }
156
157
158 BitmapMenu::~BitmapMenu()
159 {
160  if (next) // DEL LINE
161          delete next;
162  if (form->visible) Hide();
163  fl_free_form(form);  
164  delete[] bitmap;
165 }
166
167
168 void BitmapMenu::Hide()
169 {
170    fl_hide_form(form);
171    fl_set_button(button, 0);
172    active = 0;
173 }
174
175
176 void BitmapMenu::Show()
177 {
178    if (active)
179      active->Hide();
180    active = this;
181    //   int x = button->form->x + button->x, y = button->form->y + button->y;
182    //   fl_set_form_position(form, x, y + button->h);
183    fl_set_button(button, 1);
184    fl_show_form(form, FL_PLACE_MOUSE, FL_NOBORDER, "");
185 }
186
187 FL_OBJECT *
188 BitmapMenu::AddBitmap(int id, int nx, int ny, int bw, int bh, unsigned char const * data, Bool vert)
189 {
190    if (i >= nb)
191      return 0;
192    int wx = bw+ww/2, wy = bh+ww/2;
193    wx += (wx % nx);
194    wy += (wy % ny); 
195    FL_OBJECT * obj = fl_create_bmtable(1, x, y, wx, wy, "");   
196    fl_set_object_callback(obj, math_cb, id);
197    fl_set_object_lcol(obj, FL_BLUE);    
198    fl_set_object_boxtype(obj, FL_UP_BOX);   
199    fl_set_bmtable_data(obj, nx, ny, bw, bh, data);
200    if (vert) { 
201       y += wy + 8;
202       h = max(y, h);
203       w = max(x + wx + ww, w);
204    } else  {
205       x += wx + 8;
206       w = max(x, w);
207       h = max(y + wy + ww, h);
208    }
209    bitmap[i++] = obj;
210    return obj;
211 }
212
213 void BitmapMenu::Create()
214 {
215    if (i < nb)  {
216            lyxerr << "Error: Bitmaps not created!" << endl;
217       return;
218    }
219    form = fl_bgn_form(FL_UP_BOX, w, h);   
220    for (i = 0; i < nb; ++i) {
221       fl_add_object(form, bitmap[i]);
222       bitmap[i]->u_vdata = this;
223    }
224    fl_end_form();
225    fl_register_raw_callback(form, KeyPressMask, C_peek_event);
226 }
227
228 int BitmapMenu::GetIndex(FL_OBJECT* ob)
229 {
230    if (active == this) {
231       int k = 0;
232       for (i = 0; i < nb; ++i) {
233          if (bitmap[i] == ob) 
234            return k+fl_get_bmtable(ob);
235          k += fl_get_bmtable_maxitems(bitmap[i]);
236       }
237    }
238    return -1;
239 }
240
241 int peek_event(FL_FORM * /*form*/, void *xev)
242 {
243    if (BitmapMenu::active == 0)
244      return 0;
245   
246    if(static_cast<XEvent *>(xev)->type == ButtonPress)
247    {
248          BitmapMenu::active->Hide();
249          return 1;
250    }
251    if(static_cast<XEvent *>(xev)->type == KeyPress)
252    {
253       char c[5];
254       KeySym keysym;
255       XLookupString(&static_cast<XEvent *>(xev)->xkey, &c[0], 5, &keysym, 0);
256       if (keysym == XK_Left) 
257         BitmapMenu::active->Prev(); else
258       if (keysym == XK_Right) 
259         BitmapMenu::active->Next(); 
260       else 
261         BitmapMenu::active->Hide();
262       return 1;
263    }
264    return 0;  
265 }
266
267 // This is just a wrapper.
268 extern "C" int C_peek_event(FL_FORM *form, void *ptr) {
269   return peek_event(form, ptr);
270 }
271
272
273 extern "C" void math_cb(FL_OBJECT* ob, long data)
274 {
275    BitmapMenu* menu = (BitmapMenu*)ob->u_vdata;
276    int i = menu->GetIndex(ob);   
277    char const *s = 0;
278
279 //   lyxerr << "data[" << data << "]";
280    if (i<0) return;
281    switch (data)  {
282     case MM_GREEK: 
283       s = latex_greek[i]; 
284       break;
285     case MM_ARROW: 
286       s = latex_arrow[i]; 
287       break;  
288     case MM_BRELATS: 
289       s = latex_brel[i]; 
290       break;  
291     case MM_BOP: 
292       s = latex_bop[i]; 
293       break;  
294     case MM_VARSIZE: 
295       s = latex_varsz[i];  
296       break;
297     case MM_MISC: 
298       s = latex_misc[i];  
299       break;
300     case MM_DOTS: 
301 //      lyxerr << "dots[" << latex_dots[i] << " " << i << "]";
302       s = latex_dots[i-29];  
303       break;
304    }
305   
306    if (s)  {
307       if (current_view->available() && lyxrc->display_shortcuts) {
308           current_view->owner()->getMiniBuffer()->Set("Inserting symbol ", s);
309       }
310       current_view->owner()->getLyXFunc()->Dispatch(LFUN_INSERT_MATH, s);
311    }      
312    if (menu)  
313      menu->Hide(); 
314 }
315
316 char const ** get_pixmap_from_symbol(char const * arg, int wx, int hx)
317 {
318    char const ** data = 0;                  
319    latexkeys * l = in_word_set (arg, strlen(arg));
320    if (!l) 
321     return 0;
322     
323    switch (l->token) {
324     case LM_TK_FRAC:
325       data = mathed_get_pixmap_from_icon(MM_FRAC);
326       break;
327     case LM_TK_SQRT: 
328       data = mathed_get_pixmap_from_icon(MM_SQRT);
329       break;
330     case LM_TK_BIGSYM:
331     case LM_TK_SYM:
332        // I have to use directly the bitmap data since the
333        // bitmap tables are not yet created when this
334        // function is called.
335        data = pixmapFromBitmapData(arg, wx, hx);
336        break;
337    }
338    
339    return data;
340 }
341
342 Bool math_insert_greek(char const c)
343 {
344    int i;
345    char const * s= 0;
346    
347    if ('A' <= c && c <= 'Z') {
348       if ((i = Latin2Greek[c - 'A']) >= 0)
349         s = latex_greek[i];
350    }   
351    if ('a'<= c && c<= 'z') {
352       if ((i= latin2greek[c - 'a'])>= 0)
353         s = latex_greek[i+11];
354    }
355    if (s) {
356       math_insert_symbol(s);
357       if (greek_kb_flag<2) {
358          greek_kb_flag = 0;
359          current_view->unlockInset(current_view->the_locking_inset);
360       }
361       return True;
362    } else
363      return False; 
364 }
365
366
367 void math_insert_symbol(char const * s)
368 {
369    if (current_view->available())   {
370       if (!current_view->the_locking_inset) {
371          InsetFormula * new_inset = new InsetFormula();
372          current_view->beforeChange();
373          current_view->insertInset(new_inset);
374 //       Update(1);//BUG
375          new_inset->Edit(0, 0);
376          new_inset->InsertSymbol(s);
377       } else
378         if (current_view->the_locking_inset->LyxCode() == Inset::MATH_CODE)
379                 static_cast<InsetFormula*>(current_view->the_locking_inset)->InsertSymbol(s);
380         else 
381                 lyxerr << "Math error: attempt to write on a wrong "
382                         "class of inset." << endl;
383    }
384 }
385
386
387 BitmapMenu * sym_menu= 0;
388
389 void  create_symbol_menues(FD_panel * symb_form)
390 {
391    FL_OBJECT * obj; 
392    BitmapMenu * menu;
393    
394    sym_menu = menu = new BitmapMenu(2, symb_form->greek);
395    obj = menu->AddBitmap(MM_GREEK, 6, 2, Greek_width, Greek_height, 
396                            Greek_bits);         
397    fl_set_bmtable_maxitems(obj, 11);
398    obj = menu->AddBitmap(MM_GREEK, 7, 4, greek_width, greek_height,
399                            greek_bits); 
400    menu->Create();
401    
402    menu = new BitmapMenu(1, symb_form->boperator, menu);
403    obj = menu->AddBitmap(MM_BOP, 4, 8, bop_width, bop_height,
404                          bop_bits);      
405    fl_set_bmtable_maxitems(obj, 31);
406    menu->Create();   
407       
408    menu = new BitmapMenu(1, symb_form->brelats, menu);
409    obj = menu->AddBitmap(MM_BRELATS, 4, 9, brel_width, brel_height, 
410                          brel_bits);        
411    fl_set_bmtable_maxitems(obj, 35);       
412    menu->Create();
413    
414    menu = new BitmapMenu(3, symb_form->arrow, menu);
415    obj = menu->AddBitmap(MM_ARROW, 5, 4, arrow_width, arrow_height,
416                          arrow_bits);
417    obj = menu->AddBitmap(MM_ARROW, 2, 4, larrow_width, larrow_height, 
418                          larrow_bits, False);          
419    fl_set_bmtable_maxitems(obj, 7);
420    obj = menu->AddBitmap(MM_ARROW, 2, 2, darrow_width, darrow_height, 
421                          darrow_bits);
422    menu->Create(); 
423      
424    menu = new BitmapMenu(1, symb_form->varsize, menu);
425     obj = menu->AddBitmap(MM_VARSIZE, 3, 5, varsz_width, varsz_height, 
426                          varsz_bits);         
427    fl_set_bmtable_maxitems(obj, 14);
428    menu->Create();
429       
430    menu = new BitmapMenu(2, symb_form->misc, menu);
431      obj = menu->AddBitmap(MM_MISC, 5, 6, misc_width, misc_height,
432                            misc_bits);         
433      fl_set_bmtable_maxitems(obj, 29);
434      obj = menu->AddBitmap(MM_DOTS, 4, 1, dots_width, dots_height, 
435                            dots_bits);         
436    menu->Create();
437 }
438
439 static
440 char const ** pixmapFromBitmapData(char const * s, int wx, int hx)
441 {
442     int i;
443     char const ** data = 0;
444     
445     int id = -1;
446     
447     for (i = 0; i < 6; ++i) {
448         char const ** latex_str = 0;
449         switch (i) {
450          case 0: latex_str = latex_greek; break;
451          case 1: latex_str = latex_bop; break;
452          case 2: latex_str = latex_brel; break;
453          case 3: latex_str = latex_arrow; break;
454          case 4: latex_str = latex_varsz; break;
455          case 5: latex_str = latex_misc; break;
456         }
457         
458         for (int k = 0; latex_str[k][0] > ' '; ++k) {
459             if (strcmp(latex_str[k], s) == 0) {
460                 id = k;
461                 break;
462             }
463         }
464         if (id >= 0) break;
465     }
466     if (i < 6 && id >= 0) {
467         unsigned char const * bdata = 0;
468         int w = 0, h = 0, dw = 0, dh = 0;
469
470         lyxerr[Debug::MATHED] << "Imando " << i << ", " << id << endl;
471         switch (i) {
472          case 0: 
473             if (id<= 10) {
474                 w = Greek_width;
475                 h = Greek_height;
476                 bdata = Greek_bits;
477                 dw = 6;  dh = 2;
478             } else {
479                 w = greek_width;
480                 h = greek_height;
481                 bdata = greek_bits;
482                 dw = 7;  dh = 4;
483                 id -= 11;
484             }
485             break;
486          case 1:
487             w = bop_width;
488             h = bop_height;
489             bdata = bop_bits;
490             dw = 4;  dh = 8;
491             break;
492          case 2:
493             w = brel_width;
494             h = brel_height;
495             bdata = brel_bits;
496             dw = 4;  dh = 9;
497             break;
498          case 3:
499             if (id<20) {                
500                 w = arrow_width;
501                 h = arrow_height;
502                 bdata = arrow_bits;
503                 dw = 5;  dh = 4;
504             } else if (id>28) {         
505                 w = darrow_width;
506                 h = darrow_height;
507                 bdata = darrow_bits;
508                 dw = 2;  dh = 2;
509                 id -= 29;
510             } else {            
511                 w = larrow_width;
512                 h = larrow_height;
513                 bdata = larrow_bits;
514                 dw = 2;  dh = 4;
515                 id -= 20;
516             }
517             break;
518          case 4:
519             w = varsz_width;
520             h = varsz_height;
521             bdata = varsz_bits;
522             dw = 3;  dh = 5;
523             break;
524          case 5:
525             w = misc_width;
526             h = misc_height;
527             bdata = misc_bits;
528             dw = 5;  dh = 6;
529             break;
530         }
531         int ww = w/dw, hh = h/dh, x, y;
532    
533         XImage * xima = XCreateImage(fl_display, 0, 1, XYBitmap, 0, 
534                                     const_cast<char*>(reinterpret_cast<char const *>(bdata)), w, h, 8, 0);
535         xima->byte_order = LSBFirst;
536         xima->bitmap_bit_order = LSBFirst;
537         x = (id % dw)*ww;
538         y = (id/dw)*hh;
539         if (ww > wx) ww = wx;
540         if (hh > hx) hh = hx;
541         XImage * sbima = XSubImage(xima, x, y, ww, hh);
542         XpmCreateDataFromImage(fl_display, const_cast<char***>(&data), sbima, sbima, 0);
543         
544         // Dirty hack to get blue symbols quickly
545         char * sx = strstr(data[2], "FFFFFFFF");
546         if (sx) {
547             for (int k = 0; k < 8; ++k) sx[k] = '0';
548         }
549
550 //      XDestroyImage(xima);
551     }
552
553     return data;
554 }
555