]> git.lyx.org Git - lyx.git/blob - src/mathed/math_symbols.C
the figinsetpatch some lyxrc changes, read the ChangeLog
[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: 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 #include "lyxfunc.h"
37
38 #include "formula.h"
39
40 #include "math_panel.h"                 
41 #include "math_parser.h"
42
43 extern short greek_kb_flag;
44
45 extern BufferView * current_view;
46
47 /* Bitmaps */
48 #include "greek.xbm"
49 #include "arrows.xbm"
50 #include "brel.xbm"
51 #include "bop.xbm"
52 #include "misc.xbm"           
53 #include "varsz.xbm"           
54 #include "dots.xbm"
55
56 /* Latex code for those bitmaps */
57 static char const * latex_greek[] =  {
58    "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi",
59    "Sigma", "Upsilon", "Phi", "Psi", "Omega",
60    "alpha", "beta", "gamma", "delta", "epsilon", "varepsilon", "zeta",
61    "eta", "theta", "vartheta", "iota", "kappa", "lambda", "mu",
62    "nu", "xi", "pi", "varpi", "rho", "sigma", "varsigma",
63    "tau", "upsilon", "phi", "varphi", "chi", "psi", "omega", ""
64 };
65
66 static char const * latex_brel[] = {
67   "leq", "geq", "equiv", "models", 
68   "prec", "succ", "sim", "perp", 
69   "preceq", "succeq", "simeq", "mid", 
70   "ll", "gg", "asymp", "parallel", 
71   "subset", "supset", "approx", "smile", 
72   "subseteq", "supseteq", "cong", "frown", 
73   "sqsubseteq", "sqsupseteq", "doteq", "neq", 
74   "in", "ni", "propto", "notin", 
75   "vdash", "dashv", "bowtie", ""
76 };
77
78 static char const * latex_arrow[] = {
79   "downarrow", "leftarrow", "Downarrow", "Leftarrow", 
80   "hookleftarrow", "rightarrow", "uparrow", "Rightarrow", "Uparrow",
81   "hookrightarrow", "updownarrow", "Leftrightarrow", "leftharpoonup", 
82   "rightharpoonup", "rightleftharpoons", "leftrightarrow", "Updownarrow", 
83   "leftharpoondown", "rightharpoondown", "mapsto",
84   "Longleftarrow", "Longrightarrow", "Longleftrightarrow", 
85   "longleftrightarrow", "longleftarrow", "longrightarrow", "longmapsto",
86   "nwarrow", "nearrow", "swarrow", "searrow",  "",
87 };
88
89 char const * latex_varsz[] = {
90 "sum", "int", "oint", 
91 "prod", "coprod", "bigsqcup", 
92 "bigotimes", "bigodot", "bigoplus", 
93 "bigcap", "bigcup", "biguplus", 
94 "bigvee", "bigwedge", ""
95 };
96
97 static char const * latex_bop[] = {   
98   "pm", "cap", "diamond", "oplus", 
99   "mp", "cup", "bigtriangleup", "ominus", 
100   "times", "uplus", "bigtriangledown", "otimes", 
101   "div", "sqcap", "triangleright", "oslash", 
102   "cdot", "sqcup", "triangleleft", "odot", 
103   "star", "vee", "amalg", "bigcirc", 
104   "setminus", "wedge", "dagger", "circ", 
105   "bullet", "wr", "ddagger", ""
106 };
107
108 static char const * latex_misc[] = {
109   "nabla", "partial", "infty", "prime", "ell", 
110   "emptyset", "exists", "forall", "imath",  "jmath",
111   "Re", "Im", "aleph", "wp", "hbar", 
112   "angle", "top", "bot", "Vert", "neg", 
113   "flat", "natural", "sharp", "surd", "triangle", 
114   "diamondsuit", "heartsuit", "clubsuit", "spadesuit", "" 
115 };
116
117 static char const * latex_dots[] = { 
118    "ldots", "cdots", "vdots", "ddots"
119 };
120
121 static signed char latin2greek[] =  {
122   0, 1, 25, 3, 4, 23, 2, 7, 10, 24, 11, 12, 13, 14, -1, 16, 8, 18,
123   19, 21, 22, 17, 27, 15, 26, 6
124 };
125  
126 static signed char Latin2Greek[] =  {
127  -1, -1, -1, 1, -1, 8, 0, -1, -1, -1, -1, 3, -1, -1, -1,
128  5, 2, -1, 6, -1, 7, -1, 10, 4, 9, -1
129 }; 
130
131 extern char const ** mathed_get_pixmap_from_icon(int d);
132 extern "C" void math_cb(FL_OBJECT*, long);
133 static char const ** pixmapFromBitmapData(char const *, int, int);
134 void math_insert_symbol(char const * s);
135 Bool math_insert_greek(char const c);
136
137 BitmapMenu * BitmapMenu::active = 0;
138
139 BitmapMenu::BitmapMenu(int n,  FL_OBJECT * bt, BitmapMenu * prevx): nb(n)
140 {
141    w = h = 0;
142    form = 0;
143    i = 0;
144    ww = 2 * FL_abs(FL_BOUND_WIDTH);
145    x = y = ww;
146    y += 8;
147    bitmap = new FL_OBJECTP[nb];
148    button = bt;
149    button->u_vdata = this;
150    prev = prevx;
151    next = 0;
152    if (prev)
153      prev->next = this;
154 }
155
156
157 BitmapMenu::~BitmapMenu()
158 {
159         delete next;
160         if (form->visible) Hide();
161         fl_free_form(form);  
162         delete[] bitmap;
163 }
164
165
166 void BitmapMenu::Hide()
167 {
168    fl_hide_form(form);
169    fl_set_button(button, 0);
170    active = 0;
171 }
172
173
174 void BitmapMenu::Show()
175 {
176    if (active)
177      active->Hide();
178    active = this;
179    //   int x = button->form->x + button->x, y = button->form->y + button->y;
180    //   fl_set_form_position(form, x, y + button->h);
181    fl_set_button(button, 1);
182    fl_show_form(form, FL_PLACE_MOUSE, FL_NOBORDER, "");
183 }
184
185 FL_OBJECT *
186 BitmapMenu::AddBitmap(int id, int nx, int ny, int bw, int bh, unsigned char const * data, Bool vert)
187 {
188    if (i >= nb)
189      return 0;
190    int wx = bw+ww/2, wy = bh+ww/2;
191    wx += (wx % nx);
192    wy += (wy % ny); 
193    FL_OBJECT * obj = fl_create_bmtable(1, x, y, wx, wy, "");   
194    fl_set_object_callback(obj, math_cb, id);
195    fl_set_object_lcol(obj, FL_BLUE);    
196    fl_set_object_boxtype(obj, FL_UP_BOX);   
197    fl_set_bmtable_data(obj, nx, ny, bw, bh, data);
198    if (vert) { 
199       y += wy + 8;
200       h = max(y, h);
201       w = max(x + wx + ww, w);
202    } else  {
203       x += wx + 8;
204       w = max(x, w);
205       h = max(y + wy + ww, h);
206    }
207    bitmap[i++] = obj;
208    return obj;
209 }
210
211 void BitmapMenu::Create()
212 {
213    if (i < nb)  {
214            lyxerr << "Error: Bitmaps not created!" << endl;
215       return;
216    }
217    form = fl_bgn_form(FL_UP_BOX, w, h);   
218    for (i = 0; i < nb; ++i) {
219       fl_add_object(form, bitmap[i]);
220       bitmap[i]->u_vdata = this;
221    }
222    fl_end_form();
223    fl_register_raw_callback(form, KeyPressMask, C_peek_event);
224 }
225
226 int BitmapMenu::GetIndex(FL_OBJECT* ob)
227 {
228    if (active == this) {
229       int k = 0;
230       for (i = 0; i < nb; ++i) {
231          if (bitmap[i] == ob) 
232            return k+fl_get_bmtable(ob);
233          k += fl_get_bmtable_maxitems(bitmap[i]);
234       }
235    }
236    return -1;
237 }
238
239 int peek_event(FL_FORM * /*form*/, void *xev)
240 {
241    if (BitmapMenu::active == 0)
242      return 0;
243   
244    if(static_cast<XEvent *>(xev)->type == ButtonPress)
245    {
246          BitmapMenu::active->Hide();
247          return 1;
248    }
249    if(static_cast<XEvent *>(xev)->type == KeyPress)
250    {
251       char c[5];
252       KeySym keysym;
253       XLookupString(&static_cast<XEvent *>(xev)->xkey, &c[0], 5, &keysym, 0);
254       if (keysym == XK_Left) 
255         BitmapMenu::active->Prev(); else
256       if (keysym == XK_Right) 
257         BitmapMenu::active->Next(); 
258       else 
259         BitmapMenu::active->Hide();
260       return 1;
261    }
262    return 0;  
263 }
264
265 // This is just a wrapper.
266 extern "C" int C_peek_event(FL_FORM *form, void *ptr) {
267   return peek_event(form, ptr);
268 }
269
270
271 extern "C" void math_cb(FL_OBJECT* ob, long data)
272 {
273    BitmapMenu * menu = static_cast<BitmapMenu*>(ob->u_vdata);
274    int i = menu->GetIndex(ob);   
275    char const *s = 0;
276
277 //   lyxerr << "data[" << data << "]";
278    if (i<0) return;
279    switch (data)  {
280     case MM_GREEK: 
281       s = latex_greek[i]; 
282       break;
283     case MM_ARROW: 
284       s = latex_arrow[i]; 
285       break;  
286     case MM_BRELATS: 
287       s = latex_brel[i]; 
288       break;  
289     case MM_BOP: 
290       s = latex_bop[i]; 
291       break;  
292     case MM_VARSIZE: 
293       s = latex_varsz[i];  
294       break;
295     case MM_MISC: 
296       s = latex_misc[i];  
297       break;
298     case MM_DOTS: 
299 //      lyxerr << "dots[" << latex_dots[i] << " " << i << "]";
300       s = latex_dots[i-29];  
301       break;
302    }
303   
304    if (s)  {
305       if (current_view->available() && lyxrc.display_shortcuts) {
306           current_view->owner()->getMiniBuffer()->Set("Inserting symbol ", s);
307       }
308       current_view->owner()->getLyXFunc()->Dispatch(LFUN_INSERT_MATH, s);
309    }      
310    if (menu)  
311      menu->Hide(); 
312 }
313
314 char const ** get_pixmap_from_symbol(char const * arg, int wx, int hx)
315 {
316    char const ** data = 0;                  
317    latexkeys * l = in_word_set (arg, strlen(arg));
318    if (!l) 
319     return 0;
320     
321    switch (l->token) {
322     case LM_TK_FRAC:
323       data = mathed_get_pixmap_from_icon(MM_FRAC);
324       break;
325     case LM_TK_SQRT: 
326       data = mathed_get_pixmap_from_icon(MM_SQRT);
327       break;
328     case LM_TK_BIGSYM:
329     case LM_TK_SYM:
330        // I have to use directly the bitmap data since the
331        // bitmap tables are not yet created when this
332        // function is called.
333        data = pixmapFromBitmapData(arg, wx, hx);
334        break;
335    }
336    
337    return data;
338 }
339
340 Bool math_insert_greek(char const c)
341 {
342    int i;
343    char const * s= 0;
344    
345    if ('A' <= c && c <= 'Z') {
346       if ((i = Latin2Greek[c - 'A']) >= 0)
347         s = latex_greek[i];
348    }   
349    if ('a'<= c && c<= 'z') {
350       if ((i= latin2greek[c - 'a'])>= 0)
351         s = latex_greek[i+11];
352    }
353    if (s) {
354       math_insert_symbol(s);
355       if (greek_kb_flag<2) {
356          greek_kb_flag = 0;
357          current_view->unlockInset(current_view->the_locking_inset);
358       }
359       return True;
360    } else
361      return False; 
362 }
363
364
365 void math_insert_symbol(char const * s)
366 {
367    if (current_view->available())   {
368       if (!current_view->the_locking_inset) {
369          InsetFormula * new_inset = new InsetFormula();
370          current_view->beforeChange();
371          current_view->insertInset(new_inset);
372 //       Update(1);//BUG
373          new_inset->Edit(current_view, 0, 0, 0);
374          new_inset->InsertSymbol(current_view, s);
375       } else
376         if (current_view->the_locking_inset->LyxCode() == Inset::MATH_CODE)
377                 static_cast<InsetFormula*>(current_view->the_locking_inset)->InsertSymbol(current_view, s);
378         else 
379                 lyxerr << "Math error: attempt to write on a wrong "
380                         "class of inset." << endl;
381    }
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