/* * File: math_symbols.C * Purpose: User interface to math symbols * Author: Alejandro Aguilar Sierra * Created: November 1995 * Version: 0.8 28/03/96 * Description: Provides a GUI to introduce mathematical * symbols in lyx. * * Dependencies: Xlib, XForms, Lyx * * Copyright: (c) 1995, 1996, Alejandro Aguilar Sierra * * You are free to use and modify it under the terms of * the GNU General Public Licence version 2 or later. */ #include #include XPM_H_LOCATION #ifdef __GNUG__ #pragma implementation "math_panel.h" #endif #include using std::max; #include "lyx_main.h" #include "buffer.h" #include "BufferView.h" #include "minibuffer.h" #include "lyxrc.h" #include "LyXView.h" #include "support/lstrings.h" #include "debug.h" #include "formula.h" #include "math_panel.h" #include "math_parser.h" extern void SmallUpdate(signed char); extern void BeforeChange(); extern void Update(signed char); extern int UnlockInset(UpdatableInset*); extern short greek_kb_flag; extern MiniBuffer *minibuffer; extern BufferView *current_view; /* Bitmaps */ #include "greek.xbm" #include "arrows.xbm" #include "brel.xbm" #include "bop.xbm" #include "misc.xbm" #include "varsz.xbm" #include "dots.xbm" /* Latex code for those bitmaps */ static char const *latex_greek[] = { "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon", "Phi", "Psi", "Omega", "alpha", "beta", "gamma", "delta", "epsilon", "varepsilon", "zeta", "eta", "theta", "vartheta", "iota", "kappa", "lambda", "mu", "nu", "xi", "pi", "varpi", "rho", "sigma", "varsigma", "tau", "upsilon", "phi", "varphi", "chi", "psi", "omega", "" }; static char const *latex_brel[] = { "leq", "geq", "equiv", "models", "prec", "succ", "sim", "perp", "preceq", "succeq", "simeq", "mid", "ll", "gg", "asymp", "parallel", "subset", "supset", "approx", "smile", "subseteq", "supseteq", "cong", "frown", "sqsubseteq", "sqsupseteq", "doteq", "neq", "in", "ni", "propto", "notin", "vdash", "dashv", "bowtie", "" }; static char const* latex_arrow[] = { "downarrow", "leftarrow", "Downarrow", "Leftarrow", "hookleftarrow", "rightarrow", "uparrow", "Rightarrow", "Uparrow", "hookrightarrow","updownarrow", "Leftrightarrow", "leftharpoonup", "rightharpoonup", "rightleftharpoons", "leftrightarrow", "Updownarrow", "leftharpoondown", "rightharpoondown", "mapsto", "Longleftarrow", "Longrightarrow", "Longleftrightarrow", "longleftrightarrow", "longleftarrow", "longrightarrow", "longmapsto", "nwarrow", "nearrow", "swarrow", "searrow", "", }; char const* latex_varsz[] = { "sum", "int", "oint", "prod", "coprod", "bigsqcup", "bigotimes", "bigodot", "bigoplus", "bigcap", "bigcup", "biguplus", "bigvee", "bigwedge", "" }; static char const* latex_bop[] = { "pm", "cap", "diamond", "oplus", "mp", "cup", "bigtriangleup", "ominus", "times", "uplus", "bigtriangledown", "otimes", "div", "sqcap", "triangleright", "oslash", "cdot", "sqcup", "triangleleft", "odot", "star", "vee", "amalg", "bigcirc", "setminus", "wedge", "dagger", "circ", "bullet", "wr", "ddagger", "" }; static char const* latex_misc[] = { "nabla", "partial", "infty", "prime", "ell", "emptyset", "exists", "forall", "imath", "jmath", "Re", "Im", "aleph", "wp", "hbar", "angle", "top", "bot", "Vert", "neg", "flat", "natural", "sharp", "surd", "triangle", "diamondsuit", "heartsuit", "clubsuit", "spadesuit", "" }; static char const* latex_dots[] = { "ldots", "cdots", "vdots", "ddots" }; static signed char latin2greek[] = { 0, 1, 25, 3, 4, 23, 2, 7, 10, 24, 11, 12, 13, 14, -1, 16, 8, 18, 19, 21, 22, 17, 27, 15, 26, 6 }; static signed char Latin2Greek[] = { -1, -1, -1, 1, -1, 8, 0, -1, -1, -1, -1, 3, -1, -1, -1, 5, 2, -1, 6, -1, 7, -1, 10, 4, 9, -1 }; extern char** mathed_get_pixmap_from_icon(int d); extern "C" void math_cb(FL_OBJECT*, long); static char** pixmapFromBitmapData(char const *, int, int); void math_insert_symbol(char const* s); Bool math_insert_greek(char const c); BitmapMenu *BitmapMenu::active = 0; BitmapMenu::BitmapMenu(int n, FL_OBJECT* bt, BitmapMenu* prevx): nb(n) { w = h = 0; form = 0; i = 0; ww = 2*FL_abs(FL_BOUND_WIDTH); x = y = ww; y += 8; bitmap = new FL_OBJECTP[nb]; button = bt; button->u_vdata = this; prev = prevx; next = 0; if (prev) prev->next = this; } BitmapMenu::~BitmapMenu() { if (next) delete next; if (form->visible) Hide(); fl_free_form(form); delete[] bitmap; } void BitmapMenu::Hide() { fl_hide_form(form); fl_set_button(button, 0); active = 0; } void BitmapMenu::Show() { if (active) active->Hide(); active = this; // int x = button->form->x + button->x, y = button->form->y + button->y; // fl_set_form_position(form, x, y + button->h); fl_set_button(button, 1); fl_show_form(form, FL_PLACE_MOUSE, FL_NOBORDER, ""); } FL_OBJECT* BitmapMenu::AddBitmap(int id, int nx, int ny, int bw, int bh, unsigned char* data, Bool vert) { if (i>=nb) return 0; int wx=bw+ww/2, wy=bh+ww/2; wx += (wx % nx); wy += (wy % ny); FL_OBJECT *obj = fl_create_bmtable(1, x, y, wx, wy, ""); fl_set_object_callback(obj, math_cb, id); fl_set_object_lcol(obj, FL_BLUE); fl_set_object_boxtype(obj, FL_UP_BOX); fl_set_bmtable_data(obj, nx, ny, bw, bh, data); if (vert) { y += wy + 8; h = max(y, h); w = max(x + wx + ww, w); } else { x += wx + 8; w = max(x, w); h = max(y + wy + ww, h); } bitmap[i++] = obj; return obj; } void BitmapMenu::Create() { if (iu_vdata = this; } fl_end_form(); fl_register_raw_callback(form, KeyPressMask, C_peek_event); } int BitmapMenu::GetIndex(FL_OBJECT* ob) { if (active==this) { int k = 0; for (i=0; itype == ButtonPress) { BitmapMenu::active->Hide(); return 1; } if(((XEvent *)xev)->type == KeyPress) { char c[5]; KeySym keysym; XLookupString(&((XEvent *)xev)->xkey, &c[0], 5, &keysym, 0); if (keysym==XK_Left) BitmapMenu::active->Prev(); else if (keysym==XK_Right) BitmapMenu::active->Next(); else BitmapMenu::active->Hide(); return 1; } return 0; } // This is just a wrapper. extern "C" int C_peek_event(FL_FORM *form, void *ptr) { return peek_event(form,ptr); } extern "C" void math_cb(FL_OBJECT* ob, long data) { BitmapMenu* menu = (BitmapMenu*)ob->u_vdata; int i = menu->GetIndex(ob); char const *s = 0; // lyxerr << "data[" << data << "]"; if (i<0) return; switch (data) { case MM_GREEK: s = latex_greek[i]; break; case MM_ARROW: s = latex_arrow[i]; break; case MM_BRELATS: s = latex_brel[i]; break; case MM_BOP: s = latex_bop[i]; break; case MM_VARSIZE: s = latex_varsz[i]; break; case MM_MISC: s = latex_misc[i]; break; case MM_DOTS: // lyxerr << "dots[" << latex_dots[i] << " " << i << "]"; s = latex_dots[i-29]; break; } if (s) { if (current_view->available() && lyxrc->display_shortcuts) { minibuffer->Set("Inserting symbol ", s); } current_view->getOwner()->getLyXFunc()->Dispatch(LFUN_INSERT_MATH, s); } if (menu) menu->Hide(); } char** get_pixmap_from_symbol(char const *arg, int wx, int hx) { char** data=0; latexkeys *l = in_word_set (arg, strlen(arg)); if (!l) return 0; switch (l->token) { case LM_TK_FRAC: data = mathed_get_pixmap_from_icon(MM_FRAC); break; case LM_TK_SQRT: data = mathed_get_pixmap_from_icon(MM_SQRT); break; case LM_TK_BIGSYM: case LM_TK_SYM: // I have to use directly the bitmap data since the // bitmap tables are not yet created when this // function is called. data = pixmapFromBitmapData(arg, wx, hx); break; } return data; } Bool math_insert_greek(char const c) { int i; char const *s=0; if ('A'<=c && c<='Z') { if ((i=Latin2Greek[c - 'A'])>=0) s = latex_greek[i]; } if ('a'<=c && c<='z') { if ((i=latin2greek[c - 'a'])>=0) s = latex_greek[i+11]; } if (s) { math_insert_symbol(s); if (greek_kb_flag<2) { greek_kb_flag = 0; UnlockInset(current_view->currentBuffer()->the_locking_inset); } return True; } else return False; } void math_insert_symbol(char const* s) { if (current_view->available()) { if (!current_view->currentBuffer()->the_locking_inset) { InsetFormula* new_inset = new InsetFormula(); BeforeChange(); current_view->currentBuffer()->insertInset(new_inset); // Update(1);//BUG new_inset->Edit(0,0); new_inset->InsertSymbol(s); } else if (current_view->currentBuffer()->the_locking_inset->LyxCode()==Inset::MATH_CODE) ((InsetFormula*)current_view->currentBuffer()->the_locking_inset)->InsertSymbol(s); else lyxerr << "Math error: attempt to write on a wrong " "class of inset." << endl; } } BitmapMenu* sym_menu=0; void create_symbol_menues(FD_panel *symb_form) { FL_OBJECT* obj; BitmapMenu* menu; sym_menu = menu = new BitmapMenu(2, symb_form->greek); obj = menu->AddBitmap(MM_GREEK, 6, 2, Greek_width, Greek_height, Greek_bits); fl_set_bmtable_maxitems(obj, 11); obj = menu->AddBitmap(MM_GREEK, 7, 4, greek_width, greek_height, greek_bits); menu->Create(); menu = new BitmapMenu(1, symb_form->boperator, menu); obj = menu->AddBitmap(MM_BOP, 4, 8, bop_width, bop_height, bop_bits); fl_set_bmtable_maxitems(obj, 31); menu->Create(); menu = new BitmapMenu(1, symb_form->brelats, menu); obj = menu->AddBitmap(MM_BRELATS, 4, 9, brel_width, brel_height, brel_bits); fl_set_bmtable_maxitems(obj, 35); menu->Create(); menu = new BitmapMenu(3, symb_form->arrow, menu); obj = menu->AddBitmap(MM_ARROW, 5, 4, arrow_width, arrow_height, arrow_bits); obj = menu->AddBitmap(MM_ARROW, 2, 4, larrow_width, larrow_height, larrow_bits, False); fl_set_bmtable_maxitems(obj, 7); obj = menu->AddBitmap(MM_ARROW, 2, 2, darrow_width, darrow_height, darrow_bits); menu->Create(); menu = new BitmapMenu(1, symb_form->varsize, menu); obj = menu->AddBitmap(MM_VARSIZE, 3, 5, varsz_width, varsz_height, varsz_bits); fl_set_bmtable_maxitems(obj, 14); menu->Create(); menu = new BitmapMenu(2, symb_form->misc, menu); obj = menu->AddBitmap(MM_MISC, 5, 6, misc_width, misc_height, misc_bits); fl_set_bmtable_maxitems(obj, 29); obj = menu->AddBitmap(MM_DOTS, 4, 1, dots_width, dots_height, dots_bits); menu->Create(); } static char** pixmapFromBitmapData(char const *s, int wx, int hx) { int i, id; char** data=0; id=-1; for (i=0; i<6; i++) { char const **latex_str = 0; switch (i) { case 0: latex_str = latex_greek; break; case 1: latex_str = latex_bop; break; case 2: latex_str = latex_brel; break; case 3: latex_str = latex_arrow; break; case 4: latex_str = latex_varsz; break; case 5: latex_str = latex_misc; break; } for (int k = 0; latex_str[k][0]>' '; k++) { if (strcmp(latex_str[k], s)==0) { id = k; break; } } if (id>=0) break; } if (i<6 && id>=0) { unsigned char *bdata = 0; int w = 0, h = 0, dw = 0, dh = 0; lyxerr[Debug::MATHED] << "Imando " << i << ", " << id << endl; switch (i) { case 0: if (id<=10) { w = Greek_width; h = Greek_height; bdata = Greek_bits; dw = 6; dh = 2; } else { w = greek_width; h = greek_height; bdata = greek_bits; dw = 7; dh = 4; id -= 11; } break; case 1: w = bop_width; h = bop_height; bdata = bop_bits; dw = 4; dh = 8; break; case 2: w = brel_width; h = brel_height; bdata = brel_bits; dw = 4; dh = 9; break; case 3: if (id<20) { w = arrow_width; h = arrow_height; bdata = arrow_bits; dw = 5; dh = 4; } else if (id>28) { w = darrow_width; h = darrow_height; bdata = darrow_bits; dw = 2; dh = 2; id -= 29; } else { w = larrow_width; h = larrow_height; bdata = larrow_bits; dw = 2; dh = 4; id -= 20; } break; case 4: w = varsz_width; h = varsz_height; bdata = varsz_bits; dw = 3; dh = 5; break; case 5: w = misc_width; h = misc_height; bdata = misc_bits; dw = 5; dh = 6; break; } int ww = w/dw, hh = h/dh, x, y; XImage *xima = XCreateImage(fl_display, 0, 1, XYBitmap, 0, reinterpret_cast(bdata), w, h, 8, 0); xima->byte_order = LSBFirst; xima->bitmap_bit_order = LSBFirst; x = (id % dw)*ww; y = (id/dw)*hh; if (ww>wx) ww = wx; if (hh>hx) hh = hx; XImage *sbima = XSubImage(xima, x, y, ww, hh); XpmCreateDataFromImage(fl_display, &data, sbima, sbima, 0); // Dirty hack to get blue symbols quickly char *sx = strstr(data[2], "FFFFFFFF"); if (sx) { for (int k=0; k<8; k++) sx[k] = '0'; } // XDestroyImage(xima); } return data; }