]> git.lyx.org Git - lyx.git/blob - src/mathed/math_symbols.C
All changes I made to have text-insets working. Look at 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: (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         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          current_view->unlockInset(current_view->the_locking_inset);
359       }
360       return True;
361    } else
362      return False; 
363 }
364
365
366 void math_insert_symbol(char const * s)
367 {
368    if (current_view->available())   {
369       if (!current_view->the_locking_inset) {
370          InsetFormula * new_inset = new InsetFormula();
371          current_view->beforeChange();
372          current_view->insertInset(new_inset);
373 //       Update(1);//BUG
374          new_inset->Edit(current_view, 0, 0, 0);
375          new_inset->InsertSymbol(current_view, s);
376       } else
377         if (current_view->the_locking_inset->LyxCode() == Inset::MATH_CODE)
378                 static_cast<InsetFormula*>(current_view->the_locking_inset)->InsertSymbol(current_view, s);
379         else 
380                 lyxerr << "Math error: attempt to write on a wrong "
381                         "class of inset." << endl;
382    }
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