]> git.lyx.org Git - lyx.git/blob - src/mathed/math_symbols.C
removed a warning from screen and added CFLAGS in lyx.spec.in.
[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 extern MiniBuffer *minibuffer;
48
49 extern BufferView *current_view;
50
51 /* Bitmaps */
52 #include "greek.xbm"
53 #include "arrows.xbm"
54 #include "brel.xbm"
55 #include "bop.xbm"
56 #include "misc.xbm"           
57 #include "varsz.xbm"           
58 #include "dots.xbm"
59
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", ""
68 };
69
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", ""
80 };
81
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",  "",
91 };
92
93 char const* latex_varsz[] = {
94 "sum", "int", "oint", 
95 "prod", "coprod", "bigsqcup", 
96 "bigotimes", "bigodot", "bigoplus", 
97 "bigcap", "bigcup", "biguplus", 
98 "bigvee", "bigwedge", ""
99 };
100
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", ""
110 };
111
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", "" 
119 };
120
121 static char const* latex_dots[] = { 
122    "ldots", "cdots", "vdots", "ddots"
123 };
124
125 static signed char latin2greek[] =  {
126   0, 1, 25, 3, 4, 23, 2, 7, 10, 24, 11, 12, 13, 14, -1, 16, 8, 18,
127   19, 21, 22, 17, 27, 15, 26, 6
128 };
129  
130 static signed char Latin2Greek[] =  {
131  -1, -1, -1, 1, -1, 8, 0, -1, -1, -1, -1, 3, -1, -1, -1,
132  5, 2, -1, 6, -1, 7, -1, 10, 4, 9, -1
133 }; 
134
135 extern char** mathed_get_pixmap_from_icon(int d);
136 extern "C" void math_cb(FL_OBJECT*, long);
137 static char** pixmapFromBitmapData(char const *, int, int);
138 void math_insert_symbol(char const* s);
139 Bool math_insert_greek(char const c);
140
141 BitmapMenu *BitmapMenu::active = 0;
142
143 BitmapMenu::BitmapMenu(int n,  FL_OBJECT* bt, BitmapMenu* prevx): nb(n)  {
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 BitmapMenu::~BitmapMenu() {
160  if (next) delete next;
161  if (form->visible) Hide();
162  fl_free_form(form);  
163  delete[] bitmap;
164 }
165
166 void BitmapMenu::Hide()  {
167    fl_hide_form(form);
168    fl_set_button(button, 0);
169    active = 0;
170 }
171
172 void BitmapMenu::Show()  {
173    if (active)
174      active->Hide();
175    active = this;
176    //   int x = button->form->x + button->x, y = button->form->y + button->y;
177    //   fl_set_form_position(form, x, y + button->h);
178    fl_set_button(button, 1);
179    fl_show_form(form, FL_PLACE_MOUSE, FL_NOBORDER, "");
180 }
181
182 FL_OBJECT*
183 BitmapMenu::AddBitmap(int id, int nx, int ny, int bw, int bh, unsigned char* data, Bool vert)
184 {
185    if (i>=nb)
186      return 0;
187    int wx=bw+ww/2, wy=bh+ww/2;
188    wx += (wx % nx);
189    wy += (wy % ny); 
190    FL_OBJECT *obj = fl_create_bmtable(1, x, y, wx, wy, "");   
191    fl_set_object_callback(obj, math_cb, id);
192    fl_set_object_lcol(obj, FL_BLUE);    
193    fl_set_object_boxtype(obj, FL_UP_BOX);   
194    fl_set_bmtable_data(obj, nx, ny, bw, bh, data);
195    if (vert) { 
196       y += wy + 8;
197       h = max(y, h);
198       w = max(x + wx + ww, w);
199    } else  {
200       x += wx + 8;
201       w = max(x, w);
202       h = max(y + wy + ww, h);
203    }
204    bitmap[i++] = obj;
205    return obj;
206 }
207
208 void BitmapMenu::Create()
209 {
210    if (i<nb)  {
211            lyxerr << "Error: Bitmaps not created!" << endl;
212       return;
213    }
214    form = fl_bgn_form(FL_UP_BOX, w, h);   
215    for (i=0; i<nb; i++) {
216       fl_add_object(form, bitmap[i]);
217       bitmap[i]->u_vdata = this;
218    }
219    fl_end_form();
220    fl_register_raw_callback(form, KeyPressMask, C_peek_event);
221 }
222
223 int BitmapMenu::GetIndex(FL_OBJECT* ob)
224 {
225    if (active==this) {
226       int k = 0;
227       for (i=0; i<nb; i++) {
228          if (bitmap[i]==ob) 
229            return k+fl_get_bmtable(ob);
230          k += fl_get_bmtable_maxitems(bitmap[i]);
231       }
232    }
233    return -1;
234 }
235
236 int peek_event(FL_FORM * /*form*/, void *xev)
237 {
238    if (BitmapMenu::active==0)
239      return 0;
240   
241    if(((XEvent *)xev)->type == ButtonPress)
242    {
243          BitmapMenu::active->Hide();
244          return 1;
245    }
246    if(((XEvent *)xev)->type == KeyPress)
247    {
248       char c[5];
249       KeySym keysym;
250       XLookupString(&((XEvent *)xev)->xkey, &c[0], 5, &keysym, 0);
251       if (keysym==XK_Left) 
252         BitmapMenu::active->Prev(); else
253       if (keysym==XK_Right) 
254         BitmapMenu::active->Next(); 
255       else 
256         BitmapMenu::active->Hide();
257       return 1;
258    }
259    return 0;  
260 }
261
262 // This is just a wrapper.
263 extern "C" int C_peek_event(FL_FORM *form, void *ptr) {
264   return peek_event(form,ptr);
265 }
266
267
268 extern "C" void math_cb(FL_OBJECT* ob, long data)
269 {
270    BitmapMenu* menu = (BitmapMenu*)ob->u_vdata;
271    int i = menu->GetIndex(ob);   
272    char const *s = 0;
273
274 //   lyxerr << "data[" << data << "]";
275    if (i<0) return;
276    switch (data)  {
277     case MM_GREEK: 
278       s = latex_greek[i]; 
279       break;
280     case MM_ARROW: 
281       s = latex_arrow[i]; 
282       break;  
283     case MM_BRELATS: 
284       s = latex_brel[i]; 
285       break;  
286     case MM_BOP: 
287       s = latex_bop[i]; 
288       break;  
289     case MM_VARSIZE: 
290       s = latex_varsz[i];  
291       break;
292     case MM_MISC: 
293       s = latex_misc[i];  
294       break;
295     case MM_DOTS: 
296 //      lyxerr << "dots[" << latex_dots[i] << " " << i << "]";
297       s = latex_dots[i-29];  
298       break;
299    }
300   
301    if (s)  {
302       if (current_view->available() && lyxrc->display_shortcuts) {
303           minibuffer->Set("Inserting symbol ", s);
304       }
305       current_view->getOwner()->getLyXFunc()->Dispatch(LFUN_INSERT_MATH, s);
306    }      
307    if (menu)  
308      menu->Hide(); 
309 }
310
311 char** get_pixmap_from_symbol(char const *arg, int wx, int hx)
312 {
313    char** data=0;                   
314    latexkeys *l = in_word_set (arg, strlen(arg));
315    if (!l) 
316     return 0;
317     
318    switch (l->token) {
319     case LM_TK_FRAC:
320       data = mathed_get_pixmap_from_icon(MM_FRAC);
321       break;
322     case LM_TK_SQRT: 
323       data = mathed_get_pixmap_from_icon(MM_SQRT);
324       break;
325     case LM_TK_BIGSYM:
326     case LM_TK_SYM:
327        // I have to use directly the bitmap data since the
328        // bitmap tables are not yet created when this
329        // function is called.
330        data = pixmapFromBitmapData(arg, wx, hx);
331        break;
332    }
333    
334    return data;
335 }
336
337 Bool math_insert_greek(char const c)
338 {
339    int i;
340    char const *s=0;
341    
342    if ('A'<=c && c<='Z') {
343       if ((i=Latin2Greek[c - 'A'])>=0)
344         s = latex_greek[i];
345    }   
346    if ('a'<=c && c<='z') {
347       if ((i=latin2greek[c - 'a'])>=0)
348         s = latex_greek[i+11];
349    }
350    if (s) {
351       math_insert_symbol(s);
352       if (greek_kb_flag<2) {
353          greek_kb_flag = 0;
354          UnlockInset(current_view->currentBuffer()->the_locking_inset);
355       }
356       return True;
357    } else
358      return False; 
359 }
360
361 void math_insert_symbol(char const* s)
362 {
363    if (current_view->available())   {
364       if (!current_view->currentBuffer()->the_locking_inset) {
365          InsetFormula* new_inset = new InsetFormula();
366          BeforeChange();
367          current_view->currentBuffer()->insertInset(new_inset);
368 //       Update(1);//BUG
369          new_inset->Edit(0,0);
370          new_inset->InsertSymbol(s);
371       } else
372         if (current_view->currentBuffer()->the_locking_inset->LyxCode()==Inset::MATH_CODE)
373           ((InsetFormula*)current_view->currentBuffer()->the_locking_inset)->InsertSymbol(s);
374         else 
375                 lyxerr << "Math error: attempt to write on a wrong "
376                         "class of inset." << endl;
377    }
378 }
379
380 BitmapMenu* sym_menu=0;
381
382 void  create_symbol_menues(FD_panel *symb_form)
383 {
384    FL_OBJECT* obj; 
385    BitmapMenu* menu;
386    
387    sym_menu = menu = new BitmapMenu(2, symb_form->greek);
388    obj = menu->AddBitmap(MM_GREEK, 6, 2, Greek_width, Greek_height, 
389                            Greek_bits);         
390    fl_set_bmtable_maxitems(obj, 11);
391    obj = menu->AddBitmap(MM_GREEK, 7, 4, greek_width, greek_height,
392                            greek_bits); 
393    menu->Create();
394    
395    menu = new BitmapMenu(1, symb_form->boperator, menu);
396    obj = menu->AddBitmap(MM_BOP, 4, 8, bop_width, bop_height,
397                          bop_bits);      
398    fl_set_bmtable_maxitems(obj, 31);
399    menu->Create();   
400       
401    menu = new BitmapMenu(1, symb_form->brelats, menu);
402    obj = menu->AddBitmap(MM_BRELATS, 4, 9, brel_width, brel_height, 
403                          brel_bits);        
404    fl_set_bmtable_maxitems(obj, 35);       
405    menu->Create();
406    
407    menu = new BitmapMenu(3, symb_form->arrow, menu);
408    obj = menu->AddBitmap(MM_ARROW, 5, 4, arrow_width, arrow_height,
409                          arrow_bits);
410    obj = menu->AddBitmap(MM_ARROW, 2, 4, larrow_width, larrow_height, 
411                          larrow_bits, False);          
412    fl_set_bmtable_maxitems(obj, 7);
413    obj = menu->AddBitmap(MM_ARROW, 2, 2, darrow_width, darrow_height, 
414                          darrow_bits);
415    menu->Create(); 
416      
417    menu = new BitmapMenu(1, symb_form->varsize, menu);
418     obj = menu->AddBitmap(MM_VARSIZE, 3, 5, varsz_width, varsz_height, 
419                          varsz_bits);         
420    fl_set_bmtable_maxitems(obj, 14);
421    menu->Create();
422       
423    menu = new BitmapMenu(2, symb_form->misc, menu);
424      obj = menu->AddBitmap(MM_MISC, 5, 6, misc_width, misc_height,
425                            misc_bits);         
426      fl_set_bmtable_maxitems(obj, 29);
427      obj = menu->AddBitmap(MM_DOTS, 4, 1, dots_width, dots_height, 
428                            dots_bits);         
429    menu->Create();
430 }
431
432 static
433 char** pixmapFromBitmapData(char const *s, int wx, int hx)
434 {
435     int i, id;
436     char** data=0;
437     
438     id=-1;
439     
440     for (i=0; i<6; i++) {
441         char const **latex_str = 0;
442         switch (i) {
443          case 0: latex_str = latex_greek; break;
444          case 1: latex_str = latex_bop; break;
445          case 2: latex_str = latex_brel; break;
446          case 3: latex_str = latex_arrow; break;
447          case 4: latex_str = latex_varsz; break;
448          case 5: latex_str = latex_misc; break;
449         }
450         
451         for (int k = 0; latex_str[k][0]>' '; k++) {
452             if (strcmp(latex_str[k], s)==0) {
453                 id = k;
454                 break;
455             }
456         }
457         if (id>=0) break;
458     }
459     if (i<6 && id>=0) {
460         unsigned char *bdata = 0;
461         int w = 0, h = 0, dw = 0, dh = 0;
462
463         lyxerr[Debug::MATHED] << "Imando " << i << ", " << id << endl;
464         switch (i) {
465          case 0: 
466             if (id<=10) {
467                 w = Greek_width;
468                 h = Greek_height;
469                 bdata = Greek_bits;
470                 dw = 6;  dh = 2;
471             } else {
472                 w = greek_width;
473                 h = greek_height;
474                 bdata = greek_bits;
475                 dw = 7;  dh = 4;
476                 id -= 11;
477             }
478             break;
479          case 1:
480             w = bop_width;
481             h = bop_height;
482             bdata = bop_bits;
483             dw = 4;  dh = 8;
484             break;
485          case 2:
486             w = brel_width;
487             h = brel_height;
488             bdata = brel_bits;
489             dw = 4;  dh = 9;
490             break;
491          case 3:
492             if (id<20) {                
493                 w = arrow_width;
494                 h = arrow_height;
495                 bdata = arrow_bits;
496                 dw = 5;  dh = 4;
497             } else if (id>28) {         
498                 w = darrow_width;
499                 h = darrow_height;
500                 bdata = darrow_bits;
501                 dw = 2;  dh = 2;
502                 id -= 29;
503             } else {            
504                 w = larrow_width;
505                 h = larrow_height;
506                 bdata = larrow_bits;
507                 dw = 2;  dh = 4;
508                 id -= 20;
509             }
510             break;
511          case 4:
512             w = varsz_width;
513             h = varsz_height;
514             bdata = varsz_bits;
515             dw = 3;  dh = 5;
516             break;
517          case 5:
518             w = misc_width;
519             h = misc_height;
520             bdata = misc_bits;
521             dw = 5;  dh = 6;
522             break;
523         }
524         int ww = w/dw, hh = h/dh, x, y;
525    
526         XImage *xima = XCreateImage(fl_display, 0, 1, XYBitmap, 0, 
527                                     reinterpret_cast<char*>(bdata), w, h, 8, 0);
528         xima->byte_order = LSBFirst;
529         xima->bitmap_bit_order = LSBFirst;
530         x = (id % dw)*ww;
531         y = (id/dw)*hh;
532         if (ww>wx) ww = wx;
533         if (hh>hx) hh = hx;
534         XImage *sbima = XSubImage(xima, x, y, ww, hh);
535         XpmCreateDataFromImage(fl_display, &data, sbima, sbima, 0);
536         
537         // Dirty hack to get blue symbols quickly
538         char *sx = strstr(data[2], "FFFFFFFF");
539         if (sx) {
540             for (int k=0; k<8; k++) sx[k] = '0';
541         }
542
543 //      XDestroyImage(xima);
544     }
545
546     return data;
547 }
548