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