]> git.lyx.org Git - lyx.git/blob - src/mathed/math_symbols.C
my changes during the holidyas...i expect some compilers to have some problems, but...
[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 BeforeChange();
43 extern void Update(signed char);
44 extern int UnlockInset(UpdatableInset *);
45 extern short greek_kb_flag;
46
47 extern BufferView * current_view;
48
49 /* Bitmaps */
50 #include "greek.xbm"
51 #include "arrows.xbm"
52 #include "brel.xbm"
53 #include "bop.xbm"
54 #include "misc.xbm"           
55 #include "varsz.xbm"           
56 #include "dots.xbm"
57
58 /* Latex code for those bitmaps */
59 static char const * latex_greek[] =  {
60    "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi",
61    "Sigma", "Upsilon", "Phi", "Psi", "Omega",
62    "alpha", "beta", "gamma", "delta", "epsilon", "varepsilon", "zeta",
63    "eta", "theta", "vartheta", "iota", "kappa", "lambda", "mu",
64    "nu", "xi", "pi", "varpi", "rho", "sigma", "varsigma",
65    "tau", "upsilon", "phi", "varphi", "chi", "psi", "omega", ""
66 };
67
68 static char const * latex_brel[] = {
69   "leq", "geq", "equiv", "models", 
70   "prec", "succ", "sim", "perp", 
71   "preceq", "succeq", "simeq", "mid", 
72   "ll", "gg", "asymp", "parallel", 
73   "subset", "supset", "approx", "smile", 
74   "subseteq", "supseteq", "cong", "frown", 
75   "sqsubseteq", "sqsupseteq", "doteq", "neq", 
76   "in", "ni", "propto", "notin", 
77   "vdash", "dashv", "bowtie", ""
78 };
79
80 static char const * latex_arrow[] = {
81   "downarrow", "leftarrow", "Downarrow", "Leftarrow", 
82   "hookleftarrow", "rightarrow", "uparrow", "Rightarrow", "Uparrow",
83   "hookrightarrow", "updownarrow", "Leftrightarrow", "leftharpoonup", 
84   "rightharpoonup", "rightleftharpoons", "leftrightarrow", "Updownarrow", 
85   "leftharpoondown", "rightharpoondown", "mapsto",
86   "Longleftarrow", "Longrightarrow", "Longleftrightarrow", 
87   "longleftrightarrow", "longleftarrow", "longrightarrow", "longmapsto",
88   "nwarrow", "nearrow", "swarrow", "searrow",  "",
89 };
90
91 char const * latex_varsz[] = {
92 "sum", "int", "oint", 
93 "prod", "coprod", "bigsqcup", 
94 "bigotimes", "bigodot", "bigoplus", 
95 "bigcap", "bigcup", "biguplus", 
96 "bigvee", "bigwedge", ""
97 };
98
99 static char const * latex_bop[] = {   
100   "pm", "cap", "diamond", "oplus", 
101   "mp", "cup", "bigtriangleup", "ominus", 
102   "times", "uplus", "bigtriangledown", "otimes", 
103   "div", "sqcap", "triangleright", "oslash", 
104   "cdot", "sqcup", "triangleleft", "odot", 
105   "star", "vee", "amalg", "bigcirc", 
106   "setminus", "wedge", "dagger", "circ", 
107   "bullet", "wr", "ddagger", ""
108 };
109
110 static char const * latex_misc[] = {
111   "nabla", "partial", "infty", "prime", "ell", 
112   "emptyset", "exists", "forall", "imath",  "jmath",
113   "Re", "Im", "aleph", "wp", "hbar", 
114   "angle", "top", "bot", "Vert", "neg", 
115   "flat", "natural", "sharp", "surd", "triangle", 
116   "diamondsuit", "heartsuit", "clubsuit", "spadesuit", "" 
117 };
118
119 static char const * latex_dots[] = { 
120    "ldots", "cdots", "vdots", "ddots"
121 };
122
123 static signed char latin2greek[] =  {
124   0, 1, 25, 3, 4, 23, 2, 7, 10, 24, 11, 12, 13, 14, -1, 16, 8, 18,
125   19, 21, 22, 17, 27, 15, 26, 6
126 };
127  
128 static signed char Latin2Greek[] =  {
129  -1, -1, -1, 1, -1, 8, 0, -1, -1, -1, -1, 3, -1, -1, -1,
130  5, 2, -1, 6, -1, 7, -1, 10, 4, 9, -1
131 }; 
132
133 extern char const ** mathed_get_pixmap_from_icon(int d);
134 extern "C" void math_cb(FL_OBJECT*, long);
135 static char const ** pixmapFromBitmapData(char const *, int, int);
136 void math_insert_symbol(char const * s);
137 Bool math_insert_greek(char const c);
138
139 BitmapMenu * BitmapMenu::active = 0;
140
141 BitmapMenu::BitmapMenu(int n,  FL_OBJECT * bt, BitmapMenu * prevx): nb(n)
142 {
143    w = h = 0;
144    form = 0;
145    i = 0;
146    ww = 2 * FL_abs(FL_BOUND_WIDTH);
147    x = y = ww;
148    y += 8;
149    bitmap = new FL_OBJECTP[nb];
150    button = bt;
151    button->u_vdata = this;
152    prev = prevx;
153    next = 0;
154    if (prev)
155      prev->next = this;
156 }
157
158
159 BitmapMenu::~BitmapMenu()
160 {
161  if (next) 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          UnlockInset(current_view->buffer()->the_locking_inset);
360       }
361       return True;
362    } else
363      return False; 
364 }
365
366 void math_insert_symbol(char const* s)
367 {
368    if (current_view->available())   {
369       if (!current_view->buffer()->the_locking_inset) {
370          InsetFormula * new_inset = new InsetFormula();
371          BeforeChange();
372          current_view->buffer()->insertInset(new_inset);
373 //       Update(1);//BUG
374          new_inset->Edit(0, 0);
375          new_inset->InsertSymbol(s);
376       } else
377         if (current_view->buffer()->the_locking_inset->LyxCode() == Inset::MATH_CODE)
378                 static_cast<InsetFormula*>(current_view->buffer()->the_locking_inset)->InsertSymbol(s);
379         else 
380                 lyxerr << "Math error: attempt to write on a wrong "
381                         "class of inset." << endl;
382    }
383 }
384
385 BitmapMenu * sym_menu= 0;
386
387 void  create_symbol_menues(FD_panel * symb_form)
388 {
389    FL_OBJECT * obj; 
390    BitmapMenu * menu;
391    
392    sym_menu = menu = new BitmapMenu(2, symb_form->greek);
393    obj = menu->AddBitmap(MM_GREEK, 6, 2, Greek_width, Greek_height, 
394                            Greek_bits);         
395    fl_set_bmtable_maxitems(obj, 11);
396    obj = menu->AddBitmap(MM_GREEK, 7, 4, greek_width, greek_height,
397                            greek_bits); 
398    menu->Create();
399    
400    menu = new BitmapMenu(1, symb_form->boperator, menu);
401    obj = menu->AddBitmap(MM_BOP, 4, 8, bop_width, bop_height,
402                          bop_bits);      
403    fl_set_bmtable_maxitems(obj, 31);
404    menu->Create();   
405       
406    menu = new BitmapMenu(1, symb_form->brelats, menu);
407    obj = menu->AddBitmap(MM_BRELATS, 4, 9, brel_width, brel_height, 
408                          brel_bits);        
409    fl_set_bmtable_maxitems(obj, 35);       
410    menu->Create();
411    
412    menu = new BitmapMenu(3, symb_form->arrow, menu);
413    obj = menu->AddBitmap(MM_ARROW, 5, 4, arrow_width, arrow_height,
414                          arrow_bits);
415    obj = menu->AddBitmap(MM_ARROW, 2, 4, larrow_width, larrow_height, 
416                          larrow_bits, False);          
417    fl_set_bmtable_maxitems(obj, 7);
418    obj = menu->AddBitmap(MM_ARROW, 2, 2, darrow_width, darrow_height, 
419                          darrow_bits);
420    menu->Create(); 
421      
422    menu = new BitmapMenu(1, symb_form->varsize, menu);
423     obj = menu->AddBitmap(MM_VARSIZE, 3, 5, varsz_width, varsz_height, 
424                          varsz_bits);         
425    fl_set_bmtable_maxitems(obj, 14);
426    menu->Create();
427       
428    menu = new BitmapMenu(2, symb_form->misc, menu);
429      obj = menu->AddBitmap(MM_MISC, 5, 6, misc_width, misc_height,
430                            misc_bits);         
431      fl_set_bmtable_maxitems(obj, 29);
432      obj = menu->AddBitmap(MM_DOTS, 4, 1, dots_width, dots_height, 
433                            dots_bits);         
434    menu->Create();
435 }
436
437 static
438 char const ** pixmapFromBitmapData(char const * s, int wx, int hx)
439 {
440     int i;
441     char const ** data = 0;
442     
443     int id = -1;
444     
445     for (i = 0; i < 6; ++i) {
446         char const ** latex_str = 0;
447         switch (i) {
448          case 0: latex_str = latex_greek; break;
449          case 1: latex_str = latex_bop; break;
450          case 2: latex_str = latex_brel; break;
451          case 3: latex_str = latex_arrow; break;
452          case 4: latex_str = latex_varsz; break;
453          case 5: latex_str = latex_misc; break;
454         }
455         
456         for (int k = 0; latex_str[k][0]>' '; k++) {
457             if (strcmp(latex_str[k], s) == 0) {
458                 id = k;
459                 break;
460             }
461         }
462         if (id >= 0) break;
463     }
464     if (i < 6 && id >= 0) {
465         unsigned char const * bdata = 0;
466         int w = 0, h = 0, dw = 0, dh = 0;
467
468         lyxerr[Debug::MATHED] << "Imando " << i << ", " << id << endl;
469         switch (i) {
470          case 0: 
471             if (id<= 10) {
472                 w = Greek_width;
473                 h = Greek_height;
474                 bdata = Greek_bits;
475                 dw = 6;  dh = 2;
476             } else {
477                 w = greek_width;
478                 h = greek_height;
479                 bdata = greek_bits;
480                 dw = 7;  dh = 4;
481                 id -= 11;
482             }
483             break;
484          case 1:
485             w = bop_width;
486             h = bop_height;
487             bdata = bop_bits;
488             dw = 4;  dh = 8;
489             break;
490          case 2:
491             w = brel_width;
492             h = brel_height;
493             bdata = brel_bits;
494             dw = 4;  dh = 9;
495             break;
496          case 3:
497             if (id<20) {                
498                 w = arrow_width;
499                 h = arrow_height;
500                 bdata = arrow_bits;
501                 dw = 5;  dh = 4;
502             } else if (id>28) {         
503                 w = darrow_width;
504                 h = darrow_height;
505                 bdata = darrow_bits;
506                 dw = 2;  dh = 2;
507                 id -= 29;
508             } else {            
509                 w = larrow_width;
510                 h = larrow_height;
511                 bdata = larrow_bits;
512                 dw = 2;  dh = 4;
513                 id -= 20;
514             }
515             break;
516          case 4:
517             w = varsz_width;
518             h = varsz_height;
519             bdata = varsz_bits;
520             dw = 3;  dh = 5;
521             break;
522          case 5:
523             w = misc_width;
524             h = misc_height;
525             bdata = misc_bits;
526             dw = 5;  dh = 6;
527             break;
528         }
529         int ww = w/dw, hh = h/dh, x, y;
530    
531         XImage * xima = XCreateImage(fl_display, 0, 1, XYBitmap, 0, 
532                                     const_cast<char*>(reinterpret_cast<char const *>(bdata)), w, h, 8, 0);
533         xima->byte_order = LSBFirst;
534         xima->bitmap_bit_order = LSBFirst;
535         x = (id % dw)*ww;
536         y = (id/dw)*hh;
537         if (ww > wx) ww = wx;
538         if (hh > hx) hh = hx;
539         XImage * sbima = XSubImage(xima, x, y, ww, hh);
540         XpmCreateDataFromImage(fl_display, const_cast<char***>(&data), sbima, sbima, 0);
541         
542         // Dirty hack to get blue symbols quickly
543         char * sx = strstr(data[2], "FFFFFFFF");
544         if (sx) {
545             for (int k = 0; k < 8; ++k) sx[k] = '0';
546         }
547
548 //      XDestroyImage(xima);
549     }
550
551     return data;
552 }
553