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