]> git.lyx.org Git - lyx.git/blob - src/toolbar.C
remove bogus backslashed from iso-8859-1, try to fix insert and encodeString, fixes...
[lyx.git] / src / toolbar.C
1 /* This file is part of
2  * ====================================================== 
3  * 
4  *           LyX, The Document Processor
5  *
6  *           Copyright 1995 Matthias Ettrich
7  *           Copyright 1995-1999 The LyX Team.
8  *
9  *           This file is Copyright 1996-1998
10  *           Lars Gullik Bjønnes
11  *
12  * ====================================================== */
13
14 //  Added pseudo-action handling, asierra 180296
15
16 #include <config.h>
17
18 #ifdef __GNUG__
19 #pragma implementation "toolbar.h"
20 #endif
21
22 #include "lyx_main.h"
23 #include "lyx_gui_misc.h"
24 #include "lyx.h"
25 #include "toolbar.h"
26 #include "lyxfunc.h"
27 #include "lyxlex.h"
28 #include "debug.h"
29 #include "combox.h"
30 #include "lyx_cb.h"
31 #include "LyXView.h"
32 #include "LyXAction.h"
33 #include "support/lstrings.h"
34
35 #ifdef TWO_COLOR_ICONS
36 #include "cut_bw.xpm"
37 #include "emph_bw.xpm"
38 #include "fig_bw.xpm"
39 #include "foot_bw.xpm"
40 #include "math_bw.xpm"
41 #include "depth_bw.xpm"
42 #include "margin_bw.xpm"
43 #include "melt_bw.xpm"
44 #include "copy_bw.xpm"
45 #include "noun_bw.xpm"
46 #include "paste_bw.xpm"
47 #include "free_bw.xpm"
48 #include "tab_bw.xpm"
49 #include "tex_bw.xpm"
50 #include "open_bw.xpm"
51 #include "close_bw.xpm"
52 #include "save_bw.xpm"
53 #include "print1_bw.xpm"
54 #include "quit_bw.xpm"
55 #include "typeset_ps_bw.xpm"
56 #include "unknown_bw.xpm"
57 #else 
58 #include "cut.xpm"
59 #include "emph.xpm"
60 #include "fig.xpm"
61 #include "foot.xpm"
62 #include "math.xpm"
63 #include "depth.xpm"
64 #include "margin.xpm"
65 #include "melt.xpm"
66 #include "copy.xpm"
67 #include "noun.xpm"
68 #include "paste.xpm"
69 #include "free.xpm"
70 #include "tab.xpm"
71 #include "tex.xpm"
72 #include "open.xpm"
73 #include "close.xpm"
74 #include "save.xpm"
75 #include "print1.xpm"
76 #include "quit.xpm"
77 #include "typeset_ps.xpm"
78 #include "unknown.xpm"
79 #endif
80
81 // These pixmaps are the same regardless of color:
82 #include "bold_bw.xpm"
83 #include "make_ascii_bw.xpm"
84 #include "make_latex_bw.xpm"
85 #include "run_latex_bw.xpm"
86 #include "sans_bw.xpm"
87 #include "view_dvi_bw.xpm"
88 #include "view_ps_bw.xpm"
89 #include "layout_code.xpm"
90 #include "layout_latex.xpm"
91 #include "layout_scrap.xpm"
92 #include "layout_sec.xpm"
93 #include "layout_std.xpm"
94 #include "build.xpm"
95
96 // this one is not "C" because combox callbacks are really C++ %-|
97 extern void LayoutsCB(int, void *);
98 extern char const ** get_pixmap_from_symbol(char const * arg, int, int);
99 extern LyXAction lyxaction;
100
101
102 enum _tooltags {
103         TO_ADD = 1,
104         TO_ENDTOOLBAR,
105         TO_SEPARATOR,
106         TO_LAYOUTS,
107         TO_NEWLINE,
108         TO_LAST
109 };
110
111
112 struct keyword_item toolTags[TO_LAST - 1] = {
113         { "\\add", TO_ADD },
114         { "\\end_toolbar", TO_ENDTOOLBAR },
115         { "\\layouts", TO_LAYOUTS },
116         { "\\newline", TO_NEWLINE },
117         { "\\separator", TO_SEPARATOR }
118 };
119
120
121 Toolbar::Toolbar(Toolbar const &rct, LyXView *o, int x, int y)
122         : owner(o), sxpos(x), sypos(y)
123 {
124         combox = 0;
125         bubble_timer = 0;
126         reset();
127
128         // extracts the toolbar struct form rct.
129         toolbarItem * tmplist = rct.toollist;
130         while (tmplist != 0) {
131                 add(tmplist->action);
132                 lyxerr[Debug::TOOLBAR] << "tool action: "
133                                        << tmplist->action << endl;
134                 tmplist= tmplist->next;
135         }
136 }
137
138
139 // timer-cb for bubble-help (Matthias)
140 void Toolbar::BubbleTimerCB(FL_OBJECT *, long data)
141 {
142         FL_OBJECT * ob = reinterpret_cast<FL_OBJECT*>(data);
143         char * help = static_cast<char*>(ob->u_vdata);
144         fl_show_oneliner(help, ob->form->x + ob->x,
145                          ob->form->y + ob->y + ob->h);
146 }
147
148
149 extern "C" void C_Toolbar_BubbleTimerCB(FL_OBJECT * ob, long data)
150 {
151         Toolbar::BubbleTimerCB(ob, data);
152 }
153
154
155 // post_handler for bubble-help (Matthias)
156 int Toolbar::BubblePost(FL_OBJECT *ob, int event,
157                         FL_Coord /*mx*/, FL_Coord /*my*/,
158                         int /*key*/, void */*xev*/)
159 {
160         string help = static_cast<char *>(ob->u_vdata);
161         Toolbar * t = reinterpret_cast<Toolbar*>(ob->u_ldata);
162         
163         if(event == FL_ENTER && !help.empty()){
164                 fl_set_object_callback(t->bubble_timer,
165                                        C_Toolbar_BubbleTimerCB,
166                                        reinterpret_cast<long>(ob));
167                 fl_set_timer(t->bubble_timer, 1);
168         }
169         else if(event != FL_MOTION){
170                 fl_set_timer(t->bubble_timer, 0);
171                 fl_hide_oneliner();
172         }
173         return 0;
174 }
175
176
177 extern "C" int C_Toolbar_BubblePost(FL_OBJECT * ob, int event,
178                                     FL_Coord /*mx*/, FL_Coord /*my*/, 
179                                     int key, void * xev)
180 {
181         return Toolbar::BubblePost(ob, event, 0, 0, key, xev);
182 }
183
184
185 void Toolbar::activate()
186 {
187         toolbarItem * tmp= 0;
188         toolbarItem * item = toollist;
189         while(item){
190                 tmp = item->next;
191                 if (item->icon) {
192                         fl_activate_object(item->icon);
193                 }
194                 item = tmp;
195         }
196 }
197
198
199 void Toolbar::deactivate()
200 {
201         toolbarItem * tmp= 0;
202         toolbarItem * item = toollist;
203         while(item){
204                 tmp = item->next;
205                 if (item->icon) {
206                         fl_deactivate_object(item->icon);
207                 }
208                 item = tmp;
209         }
210 }
211
212
213 void Toolbar::ToolbarCB(FL_OBJECT * ob, long ac)
214 {
215         Toolbar * t = reinterpret_cast<Toolbar*>(ob->u_ldata);
216         
217         string res = t->owner->getLyXFunc()->Dispatch(int(ac));
218         if(!res.empty())
219                 lyxerr[Debug::TOOLBAR] << res << endl;
220 }
221
222
223 extern "C" void C_Toolbar_ToolbarCB(FL_OBJECT * ob, long data)
224 {
225         Toolbar::ToolbarCB(ob, data);
226 }
227
228
229 int Toolbar::get_toolbar_func(string const & func)
230 {
231         int action = lyxaction.LookupFunc(func.c_str());
232         if (action == -1) {
233                 if (func == "separator"){
234                         action = TOOL_SEPARATOR;
235                 } else if (func == "layouts"){
236                         action = TOOL_LAYOUTS;
237                 } else action = 0;
238         }
239         return action;
240 }
241
242
243 void Toolbar::init()
244 {
245         add(TOOL_LAYOUTS);
246         add(LFUN_MENUOPEN);
247         //add(LFUN_CLOSEBUFFER);
248         add(LFUN_MENUWRITE);
249         add(LFUN_MENUPRINT);
250         add(TOOL_SEPARATOR);
251
252         add(LFUN_CUT);
253         add(LFUN_COPY);
254         add(LFUN_PASTE);
255         add(TOOL_SEPARATOR);
256         
257         add(LFUN_EMPH);
258         add(LFUN_NOUN);
259         add(LFUN_FREE);
260         add(TOOL_SEPARATOR);
261         
262         add(LFUN_FOOTMELT);
263         add(LFUN_MARGINMELT);
264         add(LFUN_DEPTH);
265         add(TOOL_SEPARATOR);
266
267         add(LFUN_TEX);
268         add(LFUN_MATH_MODE);
269         add(TOOL_SEPARATOR);
270
271         add(LFUN_FIGURE);
272         add(LFUN_TABLE);
273         //add(LFUN_MELT);
274 }
275
276
277 void Toolbar::set(bool doingmain)
278 {
279         // we shouldn't set if we have not cleaned
280         if (!cleaned) return;
281         
282         FL_OBJECT * obj;
283         toolbarItem * item = toollist;
284         
285         if (!doingmain) {
286                 fl_freeze_form(owner->getForm());
287                 fl_addto_form(owner->getForm());
288         }
289
290 #if FL_REVISION < 86
291         // Ensure borderwidth is 2 to get visual feedback
292         int bw = fl_get_border_width();
293         fl_set_border_width(-2);
294 #endif
295
296         // add the time if it don't exist
297         if (bubble_timer == 0)
298                 bubble_timer = fl_add_timer(FL_HIDDEN_TIMER,
299                                             xpos, ypos, 0, 0, "Timer");
300         
301         while(item != 0) {
302                 switch(item->action){
303                 case TOOL_SEPARATOR:
304                         xpos += sepspace;
305                         item = item->next;
306                         break;
307                 case TOOL_LAYOUTS:
308                         xpos += standardspacing;
309                         if (!combox)
310                                 combox = new Combox(FL_COMBOX_DROPLIST);
311                         combox->add(xpos, ypos, 135, height, 300);
312                         combox->setcallback(LayoutsCB);
313                         combox->resize(FL_RESIZE_ALL);
314                         combox->gravity(NorthWestGravity, NorthWestGravity);
315                         item = item->next;
316                         xpos += 135;
317                         break;
318                 default:
319                         xpos += standardspacing;
320                         item->icon = obj = 
321                                 fl_add_pixmapbutton(FL_NORMAL_BUTTON,
322                                                     xpos, ypos,
323                                                     buttonwidth,
324                                                     height, "");
325                         fl_set_object_boxtype(obj, FL_UP_BOX);
326                         fl_set_object_color(obj, FL_MCOL, FL_BLUE);
327                         fl_set_object_resize(obj, FL_RESIZE_ALL);
328                         fl_set_object_gravity(obj,
329                                               NorthWestGravity,
330                                               NorthWestGravity);
331                         fl_set_object_callback(obj, C_Toolbar_ToolbarCB,
332                                                static_cast<long>(item->action));
333 #if FL_REVISION >85
334                         // Remove the blue feedback rectangle
335                         fl_set_pixmapbutton_focus_outline(obj, 0);
336 #endif
337
338                         // set the bubble-help (Matthias)
339 #warning This is dangerous!
340                         obj->u_vdata = const_cast<char*>(item->help.c_str());
341                         // we need to know what toolbar this item
342                         // belongs too. (Lgb)
343                         obj->u_ldata = reinterpret_cast<long>(this);
344                           
345                         fl_set_object_posthandler(obj, C_Toolbar_BubblePost);
346
347                         fl_set_pixmapbutton_data(obj, const_cast<char**>(item->pixmap));
348                         item = item->next;
349                         // we must remember to update the positions
350                         xpos += buttonwidth;
351                         // ypos is constant
352                         /* Here will come a check to see if the new
353                          * pos is within the bounds of the main frame,
354                          * and perhaps wrap the toolbar if not.
355                          */
356                         break;
357                 }
358         }
359 #if FL_REVISION < 86
360         // Reset borderwidth to its default value.
361         fl_set_border_width(bw);
362 #endif
363         if (!doingmain) {
364                 fl_end_form();
365                 fl_unfreeze_form(owner->getForm());
366                 // Should be safe to do this here.
367                 owner->updateLayoutChoice();
368         }
369         
370         cleaned = false;
371 }
372
373
374 char const ** Toolbar::getPixmap(kb_action action, string const & arg)
375 {
376         char const ** pixmap = unknown_xpm; //0
377         switch(action){
378         case LFUN_MENUOPEN:    pixmap = open_xpm; break;
379         case LFUN_CLOSEBUFFER: pixmap = close_xpm; break;
380         case LFUN_MENUPRINT:   pixmap = print1_xpm; break;
381         case LFUN_MENUWRITE:   pixmap = save_xpm; break;
382         case LFUN_EMPH:  pixmap = emph_xpm; break;
383         case LFUN_NOUN:        pixmap = noun_xpm; break;
384         case LFUN_FREE:        pixmap = free_xpm; break;
385         case LFUN_FOOTMELT:    pixmap = foot_xpm; break;
386         case LFUN_DEPTH:       pixmap = depth_xpm; break;
387         case LFUN_COPY:        pixmap = copy_xpm; break;
388         case LFUN_CUT:         pixmap = cut_xpm; break;
389         case LFUN_PASTE:       pixmap = paste_xpm; break;
390         case LFUN_TEX:         pixmap = tex_xpm; break;
391         case LFUN_MATH_MODE:   pixmap = math_xpm; break;
392         case LFUN_MARGINMELT:  pixmap = margin_xpm; break;
393         case LFUN_FIGURE:      pixmap = fig_xpm; break;
394         case LFUN_TABLE:       pixmap = tab_xpm; break;
395         case LFUN_MELT:        pixmap = melt_xpm; break;
396         case LFUN_QUIT:        pixmap = quit_xpm; break;
397         case LFUN_RUNDVIPS:    pixmap = update_ps_xpm; break;
398         case LFUN_EXPORT:
399         {
400                 if (arg == "ascii")
401                         pixmap = make_ascii_xpm;
402                 else if (arg == "latex")
403                         pixmap = make_latex_xpm;
404         }
405         break; 
406         case LFUN_LAYOUT:
407         {
408                 if (arg == "Section")
409                         pixmap = layout_sec_xpm;
410                 else if (arg == "LaTeX")
411                         pixmap = layout_latex_xpm;
412                 else if (arg == "LyX-Code")
413                         pixmap = layout_code_xpm;
414                 else if (arg == "Scrap")
415                         pixmap = layout_scrap_xpm;
416                 else
417                         pixmap = layout_std_xpm;
418         }
419         break;
420
421         case LFUN_BOLD : pixmap = bold_xpm; break; 
422         case LFUN_SANS: pixmap = sans_xpm; break; 
423         case LFUN_RUNLATEX: pixmap = run_latex_xpm; break; 
424         case LFUN_BUILDPROG: pixmap = build_xpm; break; 
425         case LFUN_PREVIEWPS: pixmap = view_ps_xpm; break; 
426         case LFUN_PREVIEW: pixmap = view_dvi_xpm; break; 
427         case LFUN_INSERT_MATH:
428         {
429                 if (!arg.empty())
430                         pixmap = get_pixmap_from_symbol(arg.c_str(),
431                                                         buttonwidth,
432                                                         height);
433         }
434         break;
435         default:
436                 //pixmap = unknown_xpm;
437                 break;
438         }
439         return pixmap;
440 }
441
442
443 void Toolbar::add(int action, bool doclean)
444 {
445         if (doclean && !cleaned) clean();
446
447         // this is what we do if we want to add to an existing
448         // toolbar.
449         if (!doclean && owner) {
450                 // first «hide» the toolbar buttons. This is not a real hide
451                 // actually it deletes and frees the button altogether.
452                 lyxerr << "Toolbar::add: «hide» the toolbar buttons." << endl;
453                 toolbarItem * tmp= 0;
454                 toolbarItem * item = toollist;
455
456                 lightReset();
457                 
458                 fl_freeze_form(owner->getForm());
459                 while(item){
460                         tmp = item->next;
461                         if (item->icon) {
462                                 fl_delete_object(item->icon);
463                                 fl_free_object(item->icon);
464                         }
465                         item = tmp;
466                 }
467                 if (combox) {
468                         delete combox;
469                         combox = 0;
470                 }
471                 fl_unfreeze_form(owner->getForm());
472                 cleaned = true; // this is not completely true, but OK anyway
473         }
474         
475         // there exist some special actions not part of
476         // kb_action: SEPARATOR, LAYOUTS
477         char const ** pixmap = 0;
478         string help;
479
480         toolbarItem * newItem, * tmp;
481
482         if (lyxaction.isPseudoAction(action)) {
483                 string arg;
484                 kb_action act = static_cast<kb_action>
485                         (lyxaction.retrieveActionArg(action, arg));
486                 pixmap = getPixmap(act, arg);
487                 help = lyxaction.helpText(act);
488                 help += " ";
489                 help += arg;
490                 lyxerr.debug() << "Pseudo action " << action << endl;
491         } else {
492                 pixmap = getPixmap(static_cast<kb_action>(action));
493                 help = lyxaction.helpText(static_cast<kb_action>(action));
494         }
495         
496         // adds an item to the list
497         if (pixmap != 0
498             || action == TOOL_SEPARATOR
499             || action == TOOL_LAYOUTS)
500                 {
501                         newItem = new toolbarItem;
502                         newItem->action = action;
503                         newItem->pixmap = pixmap;
504                         newItem->help = help;
505                         // the new item is placed at the end of the list
506                         tmp = toollist;
507                         if (tmp != 0){
508                                 while(tmp->next != 0)
509                                         tmp = tmp->next;
510                                 // here is tmp->next == 0
511                                 tmp->next = newItem;
512                         } else
513                                 toollist = newItem;
514                 }
515         //if (action == TOOL_LAYOUTS) {
516         //      combox = new Combox(FL_COMBOX_DROPLIST);
517         //}
518 }
519
520
521 void Toolbar::add(string const & func, bool doclean)
522 {
523         int tf = lyxaction.LookupFunc(func.c_str());
524
525         if (tf == -1){
526                 lyxerr << "Toolbar::add: no LyX command called`"
527                        << func << "'exists!" << endl; 
528         } else {
529                 add(tf, doclean);
530         }
531 }
532
533
534 void Toolbar::clean()
535 {
536         toolbarItem * tmp = 0;
537         toolbarItem * item = toollist;
538
539         reset();
540
541         //now delete all the objects..
542         if (owner)
543                 fl_freeze_form(owner->getForm());
544         while (item) {
545                 tmp = item->next;
546                 delete item;
547                 item = tmp;
548         }
549         lyxerr[Debug::TOOLBAR] << "Combox: " << combox << endl;
550         if (combox) {
551                 delete combox;
552                 combox = 0;
553         }
554         if (owner)
555                 fl_unfreeze_form(owner->getForm());
556         lyxerr[Debug::TOOLBAR] << "toolbar cleaned" << endl;
557         cleaned = true;
558 }
559
560
561 void Toolbar::push(int nth)
562 {
563         lyxerr[Debug::TOOLBAR] << "Toolbar::push: trying to trigger no `"
564                                << nth << '\'' << endl;
565         
566         if (nth == 0) return;
567
568         int count = 0;
569         toolbarItem * tmp = toollist;
570         while (tmp) {
571                 ++count;
572                 if (count == nth) {
573                         fl_trigger_object(tmp->icon);
574                         return;
575                 }
576                 tmp = tmp->next;
577         }
578         // item nth not found...
579         LyXBell();
580 }
581
582
583 void Toolbar::read(LyXLex & lex)
584 {
585         //consistency check
586         if (lex.GetString() != "\\begin_toolbar")
587                 lyxerr << "Toolbar::read: ERROR wrong token:`"
588                        << lex.GetString() << '\'' << endl;
589
590         clean();
591         string func;
592         bool quit = false;
593         
594         lex.pushTable(toolTags, TO_LAST - 1);
595
596         if (lyxerr.debugging(Debug::PARSER))
597                 lex.printTable();
598         
599         while (lex.IsOK() && !quit) {
600                 
601                 lyxerr[Debug::TOOLBAR] << "Toolbar::read: current lex text: `"
602                                        << lex.GetString() << '\'' << endl;
603
604                 switch(lex.lex()) {
605                 case TO_ADD:
606                         if (lex.EatLine()) {
607                                 func = lex.GetString();
608                                 lyxerr[Debug::TOOLBAR]
609                                         << "Toolbar::read TO_ADD func: `"
610                                         << func << "'" << endl;
611                                 add(func);
612                         }
613                         break;
614                    
615                 case TO_SEPARATOR:
616                         add(TOOL_SEPARATOR);
617                         break;
618                    
619                 case TO_LAYOUTS:
620                         add(TOOL_LAYOUTS);
621                         break;
622                    
623                 case TO_NEWLINE:
624                         add(TOOL_NEWLINE);
625                         break;
626                         
627                 case TO_ENDTOOLBAR:
628                         // should not set automatically
629                         //set();
630                         quit = true;
631                         break;
632                 default:
633                         lex.printError("Toolbar::read: "
634                                        "Unknown toolbar tag: `$$Token'");
635                         break;
636                 }
637         }
638         lex.popTable();
639 }