]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormDocument.C
b0eab6e6bd6bf7a8e0886b71c4cb55fec88fd29f
[lyx.git] / src / frontends / xforms / FormDocument.C
1 /* This file is part of
2  * ======================================================
3  * 
4  *           LyX, The Document Processor
5  *       
6  *           Copyright 2000 The LyX Team.
7  *
8  *           @author Jürgen Vigna
9  *
10  *======================================================*/
11
12 #include <config.h>
13
14 #include FORMS_H_LOCATION
15 #include XPM_H_LOCATION
16
17 #ifdef __GNUG_
18 #pragma implementation
19 #endif
20
21 #include "lyx_gui_misc.h"
22
23 #include "FormDocument.h"
24 #include "form_document.h"
25 #include "Dialogs.h"
26 #include "layout.h"
27 #include "combox.h"
28 #include "tex-strings.h"
29 #include "bufferparams.h"
30 #include "insets/insetquotes.h"
31 #include "vspace.h"
32 #include "bmtable.h"
33 #include "support/filetools.h"
34 #include "language.h"
35 #include "LyXView.h"
36 #include "BufferView.h"
37 #include "buffer.h"
38 #include "Liason.h"
39 #include "CutAndPaste.h"
40 #include "bufferview_funcs.h"
41 #include "xforms_helpers.h" 
42
43 #ifdef CXX_WORKING_NAMESPACES
44 using Liason::setMinibuffer;
45 #endif
46
47 #define USE_CLASS_COMBO 1
48
49 FormDocument::FormDocument(LyXView * lv, Dialogs * d)
50         : FormBaseBD(lv, d, _("Document Layout")), fbullet(0)
51 {
52     // let the popup be shown
53     // This is a permanent connection so we won't bother
54     // storing a copy because we won't be disconnecting.
55     d->showLayoutDocument.connect(slot(this, &FormDocument::show));
56 }
57
58
59 void FormDocument::redraw()
60 {
61         if( form() && form()->visible )
62                 fl_redraw_form( form() );
63         else
64                 return;
65
66         FL_FORM * outer_form = fl_get_active_folder(dialog_->tabbed_folder);
67         if (outer_form && outer_form->visible)
68                 fl_redraw_form( outer_form );
69 }
70
71
72 FL_FORM * FormDocument::form() const
73 {
74     if (dialog_.get()) return dialog_->form;
75     return 0;
76 }
77
78
79 void FormDocument::build()
80 {
81     int n;
82
83     // the tabbed folder
84     dialog_.reset(build_tabbed_document());
85
86     // Manage the restore, ok, apply, restore and cancel/close buttons
87     bc().setOK(dialog_->button_ok);
88     bc().setApply(dialog_->button_apply);
89     bc().setCancel(dialog_->button_cancel);
90     bc().setUndoAll(dialog_->button_restore);
91     bc().refresh();
92
93     // Workaround dumb xforms sizing bug
94     minw_ = form()->w;
95     minh_ = form()->h;
96
97     // the document paper form
98     paper_.reset(build_doc_paper());
99     fl_addto_choice(paper_->choice_papersize2,
100                     _(" Default | Custom | USletter | USlegal "
101                       "| USexecutive | A3 | A4 | A5 | B3 | B4 | B5 "));
102     fl_addto_choice(paper_->choice_paperpackage,
103                     _(" None "
104                       "| A4 small Margins (only portrait) "
105                       "| A4 very small Margins (only portrait) "
106                       "| A4 very wide margins (only portrait) "));
107     fl_set_input_return(paper_->input_custom_width, FL_RETURN_CHANGED);
108     fl_set_input_return(paper_->input_custom_height, FL_RETURN_CHANGED);
109     fl_set_input_return(paper_->input_top_margin, FL_RETURN_CHANGED);
110     fl_set_input_return(paper_->input_bottom_margin, FL_RETURN_CHANGED);
111     fl_set_input_return(paper_->input_left_margin, FL_RETURN_CHANGED);
112     fl_set_input_return(paper_->input_right_margin, FL_RETURN_CHANGED);
113     fl_set_input_return(paper_->input_head_height, FL_RETURN_CHANGED);
114     fl_set_input_return(paper_->input_head_sep, FL_RETURN_CHANGED);
115     fl_set_input_return(paper_->input_foot_skip, FL_RETURN_CHANGED);
116
117     bc().addReadOnly (paper_->choice_paperpackage);
118     bc().addReadOnly (paper_->greoup_radio_orientation);
119     bc().addReadOnly (paper_->radio_portrait);
120     bc().addReadOnly (paper_->radio_landscape);
121     bc().addReadOnly (paper_->choice_papersize2);
122     bc().addReadOnly (paper_->push_use_geometry);
123     bc().addReadOnly (paper_->input_custom_width);
124     bc().addReadOnly (paper_->input_custom_height);
125     bc().addReadOnly (paper_->input_top_margin);
126     bc().addReadOnly (paper_->input_bottom_margin);
127     bc().addReadOnly (paper_->input_left_margin);
128     bc().addReadOnly (paper_->input_right_margin);
129     bc().addReadOnly (paper_->input_head_height);
130     bc().addReadOnly (paper_->input_head_sep);
131     bc().addReadOnly (paper_->input_foot_skip);
132
133     // the document class form
134     class_.reset(build_doc_class());
135
136     FL_OBJECT * obj;
137 #ifdef USE_CLASS_COMBO
138     // The language is a combo-box and has to be inserted manually
139     obj = class_->choice_doc_class;
140     fl_deactivate_object(obj);
141     fl_addto_form(class_->form);
142     combo_doc_class.reset(new Combox(FL_COMBOX_DROPLIST));
143     combo_doc_class->add(obj->x, obj->y, obj->w, obj->h, 400,
144                          dialog_->tabbed_folder);
145     combo_doc_class->shortcut("#C",1);
146     combo_doc_class->setcallback(ComboInputCB, this);
147     fl_end_form();
148     for (LyXTextClassList::const_iterator cit = textclasslist.begin();
149          cit != textclasslist.end(); ++cit)
150     {
151         combo_doc_class->addto((*cit).description());
152     }
153 #else
154     fl_clear_choice(class_->choice_doc_class);
155     for (LyXTextClassList::const_iterator cit = textclasslist.begin();
156          cit != textclasslist.end(); ++cit)
157     {
158         fl_addto_choice(class_->choice_doc_class,(*cit).description().c_str());
159     }
160 #endif
161     fl_addto_choice(class_->choice_doc_spacing,
162                     _(" Single | OneHalf | Double | Other "));
163     fl_addto_choice(class_->choice_doc_fontsize, "default|10|11|12");
164    for (n=0; tex_fonts[n][0]; ++n) {
165         fl_addto_choice(class_->choice_doc_fonts,tex_fonts[n]);
166     }
167     fl_addto_choice(class_->choice_doc_pagestyle,
168                     "default|empty|plain|headings|fancy");
169     fl_addto_choice(class_->choice_doc_skip,
170                     _(" Smallskip | Medskip | Bigskip | Length "));
171     fl_set_input_return(class_->input_doc_extra, FL_RETURN_CHANGED);
172     fl_set_input_return(class_->input_doc_skip, FL_RETURN_CHANGED);
173     fl_set_input_return(class_->input_doc_spacing, FL_RETURN_CHANGED);
174
175     bc().addReadOnly (class_->radio_doc_indent);
176     bc().addReadOnly (class_->radio_doc_skip);
177 #ifndef USE_CLASS_COMBO
178     bc().addReadOnly (class_->choice_doc_class);
179 #endif
180     bc().addReadOnly (class_->choice_doc_pagestyle);
181     bc().addReadOnly (class_->choice_doc_fonts);
182     bc().addReadOnly (class_->choice_doc_fontsize);
183     bc().addReadOnly (class_->radio_doc_sides_one);
184     bc().addReadOnly (class_->radio_doc_sides_two);
185     bc().addReadOnly (class_->radio_doc_columns_one);
186     bc().addReadOnly (class_->radio_doc_columns_two);
187     bc().addReadOnly (class_->input_doc_extra);
188     bc().addReadOnly (class_->input_doc_skip);
189     bc().addReadOnly (class_->choice_doc_skip);
190     bc().addReadOnly (class_->choice_doc_spacing);
191     bc().addReadOnly (class_->input_doc_spacing);
192
193     // the document language form
194     language_.reset(build_doc_language());
195     fl_addto_choice(language_->choice_inputenc,
196                     "default|auto|latin1|latin2|latin5"
197                     "|koi8-r|koi8-u|cp866|cp1251|iso88595");
198
199     // The language is a combo-box and has to be inserted manually
200     obj = language_->choice_language;
201     fl_deactivate_object(obj);
202     fl_addto_form(language_->form);
203     combo_language.reset(new Combox(FL_COMBOX_DROPLIST));
204     combo_language->add(obj->x, obj->y, obj->w, obj->h, 400,
205                         dialog_->tabbed_folder);
206     combo_language->shortcut("#L",1);
207     combo_language->setcallback(ComboInputCB, this);
208     fl_end_form();
209
210     for (Languages::const_iterator cit = languages.begin();
211         cit != languages.end(); ++cit) {
212         combo_language->addto((*cit).second.lang());
213     }
214
215     fl_addto_choice(language_->choice_quotes_language,
216                     _(" ``text'' | ''text'' | ,,text`` | ,,text'' |"
217                       " «text» | »text« "));
218
219     bc().addReadOnly (language_->choice_inputenc);
220
221     // the document options form
222     options_.reset(build_doc_options());
223     fl_set_input_return(options_->input_float_placement, FL_RETURN_CHANGED);
224     fl_set_counter_bounds(options_->slider_secnumdepth,-2,5);
225     fl_set_counter_bounds(options_->slider_tocdepth,-1,5);
226     fl_set_counter_step(options_->slider_secnumdepth,1,1);
227     fl_set_counter_step(options_->slider_tocdepth,1,1);
228     fl_set_counter_precision(options_->slider_secnumdepth, 0);
229     fl_set_counter_precision(options_->slider_tocdepth, 0);
230     for (n=0; tex_graphics[n][0]; ++n) {
231         fl_addto_choice(options_->choice_postscript_driver, tex_graphics[n]);
232     }
233
234     bc().addReadOnly (options_->slider_secnumdepth);
235     bc().addReadOnly (options_->slider_tocdepth);
236     bc().addReadOnly (options_->check_use_amsmath);
237     bc().addReadOnly (options_->input_float_placement);
238     bc().addReadOnly (options_->choice_postscript_driver);
239
240     // the document bullets form
241     bullets_.reset(build_doc_bullet());
242     fl_addto_choice(bullets_->choice_bullet_size,
243                     _(" default | tiny | script | footnote | small |"
244                       " normal | large | Large | LARGE | huge | Huge"));
245     fl_set_choice(bullets_->choice_bullet_size, 1);
246     fl_set_input_return(bullets_->input_bullet_latex, FL_RETURN_CHANGED);
247     fl_set_input_maxchars(bullets_->input_bullet_latex, 80);
248
249     bc().addReadOnly (bullets_->bmtable_bullet_panel);
250     bc().addReadOnly (bullets_->choice_bullet_size);
251     bc().addReadOnly (bullets_->input_bullet_latex);
252
253     fl_addto_tabfolder(dialog_->tabbed_folder,_("Document"),
254                        class_->form);
255     fl_addto_tabfolder(dialog_->tabbed_folder,_("Paper"),
256                        paper_->form);
257     fl_addto_tabfolder(dialog_->tabbed_folder,_("Language"),
258                        language_->form);
259     fl_addto_tabfolder(dialog_->tabbed_folder,_("Extra"),
260                        options_->form);
261     fbullet = fl_addto_tabfolder(dialog_->tabbed_folder,_("Bullets"),
262                                  bullets_->form);
263     if ((XpmVersion < 4) || (XpmVersion == 4 && XpmRevision < 7)) {
264             lyxerr << _("Your version of libXpm is older than 4.7.\n"
265                         "The `bullet' tab of the document popup "
266                         "has been disabled") << '\n';
267         fl_deactivate_object(fbullet);
268         fl_set_object_lcol(fbullet, FL_INACTIVE);
269     }
270 }
271
272
273 void FormDocument::apply()
274 {
275     if (!lv_->view()->available() || !dialog_.get())
276         return;
277
278     bool redo = class_apply();
279     paper_apply();
280     redo = language_apply() || redo;
281     redo = options_apply() || redo;
282     bullets_apply();
283
284     if (redo) {
285             lv_->view()->redoCurrentBuffer();
286     }
287     lv_->buffer()->markDirty();
288     setMinibuffer(lv_, _("Document layout set"));
289 }
290
291
292 void FormDocument::cancel()
293 {
294     // this avoids confusion when reopening
295     BufferParams & param = lv_->buffer()->params;
296     param.temp_bullets[0] = param.user_defined_bullets[0];
297     param.temp_bullets[1] = param.user_defined_bullets[1];
298     param.temp_bullets[2] = param.user_defined_bullets[2];
299     param.temp_bullets[3] = param.user_defined_bullets[3];
300     hide();
301 }
302
303
304 void FormDocument::update()
305 {
306     if (!dialog_.get())
307         return;
308
309     checkReadOnly();
310
311     BufferParams const & params = lv_->buffer()->params;
312
313     class_update(params);
314     paper_update(params);
315     language_update(params);
316     options_update(params);
317     bullets_update(params);
318 }
319
320
321 bool FormDocument::input( FL_OBJECT * ob, long data )
322 {
323         State cb = static_cast<State>( data );
324
325         switch (cb) {
326         case CHECKCHOICECLASS:
327                 CheckChoiceClass(ob, 0);
328                 break;
329         case CHOICEBULLETSIZE:
330                 ChoiceBulletSize(ob, 0);
331                 break;
332         case INPUTBULLETLATEX:
333                 InputBulletLaTeX(ob, 0);
334                 break;
335         case BULLETDEPTH1:
336         case BULLETDEPTH2:
337         case BULLETDEPTH3:
338         case BULLETDEPTH4:
339                 BulletDepth(ob, cb);
340                 break;
341         case BULLETPANEL1:
342         case BULLETPANEL2:
343         case BULLETPANEL3:
344         case BULLETPANEL4:
345         case BULLETPANEL5:
346         case BULLETPANEL6:
347                 BulletPanel(ob, cb);
348                 break;
349         case BULLETBMTABLE:
350                 BulletBMTable(ob, 0);
351                 break;
352         default:
353                 break;
354         }
355         
356         switch (data) {
357         case INPUT:
358         case CHECKCHOICECLASS:
359         case CHOICEBULLETSIZE:
360         case INPUTBULLETLATEX:
361         case BULLETBMTABLE:
362                 return CheckDocumentInput(ob, 0);
363         default:
364                 break;
365         }
366
367         return true;
368 }
369
370
371 void FormDocument::ComboInputCB(int, void * v, Combox * combox)
372 {
373     FormDocument * pre = static_cast<FormDocument*>(v);
374     if (combox == pre->combo_doc_class.get())
375         pre->CheckChoiceClass(0, 0);
376     pre->bc().valid(pre->CheckDocumentInput(0,0));
377 }
378
379
380 bool FormDocument::class_apply()
381 {
382         bool redo = false;
383         BufferParams &params = lv_->buffer()->params;
384
385         // If default skip is a "Length" but there's no text in the
386         // input field, reset the kind to "Medskip", which is the default.
387         if ((fl_get_choice (class_->choice_doc_skip) == 4) &&
388             !*(fl_get_input (class_->input_doc_skip))) {
389                 fl_set_choice (class_->choice_doc_skip, 2);
390         }
391         params.fonts = fl_get_choice_text(class_->choice_doc_fonts);
392         params.fontsize = fl_get_choice_text(class_->choice_doc_fontsize);
393         params.pagestyle = fl_get_choice_text(class_->choice_doc_pagestyle);
394
395 #ifdef USE_CLASS_COMBO   
396         unsigned int const new_class = combo_doc_class->get() - 1;
397 #else
398         unsigned int const new_class = fl_get_choice(class_->choice_doc_class) - 1;
399 #endif
400         
401         if (params.textclass != new_class) {
402                 // try to load new_class
403                 if (textclasslist.Load(new_class)) {
404                         // successfully loaded
405                         redo = true;
406                         setMinibuffer(lv_, _("Converting document to new document class..."));
407                         CutAndPaste cap;
408                         int ret = cap.SwitchLayoutsBetweenClasses(
409                             params.textclass, new_class,
410                             lv_->buffer()->paragraph);
411                         if (ret) {
412                                 string s;
413                                 if (ret==1) {
414                                         s = _("One paragraph couldn't be converted");
415                                 } else {
416                                         s += tostr(ret);
417                                         s += _(" paragraphs couldn't be converted");
418                                 }
419                                 WriteAlert(_("Conversion Errors!"),s,
420                                            _("into chosen document class"));
421                         }
422                         
423                         params.textclass = new_class;
424                 } else {
425                         // problem changing class -- warn user and retain old style
426                         WriteAlert(_("Conversion Errors!"),
427                                    _("Errors loading new document class."),
428                                    _("Reverting to original document class."));
429 #ifdef USE_CLASS_COMBO
430                         combo_doc_class->select(int(params.textclass) + 1);
431 #else
432                         fl_set_choice(class_->choice_doc_class,
433                                       params.textclass + 1);
434 #endif
435                 }
436         }
437         BufferParams::PARSEP tmpsep = params.paragraph_separation;
438         if (fl_get_button(class_->radio_doc_indent))
439                 params.paragraph_separation = BufferParams::PARSEP_INDENT;
440         else
441                 params.paragraph_separation = BufferParams::PARSEP_SKIP;
442         if (tmpsep != params.paragraph_separation)
443                 redo = true;
444         
445         VSpace tmpdefskip = params.getDefSkip();
446         switch (fl_get_choice (class_->choice_doc_skip)) {
447         case 1:
448                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
449                 break;
450         case 2:
451                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
452                 break;
453     case 3:
454             params.setDefSkip(VSpace(VSpace::BIGSKIP));
455             break;
456         case 4:
457                 params.setDefSkip
458                         (VSpace(LyXGlueLength(fl_get_input(class_->input_doc_skip))));
459                 break;
460                 // DocumentDefskipCB assures that this never happens
461         default:
462                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
463                 break;
464         }
465         if (!(tmpdefskip == params.getDefSkip()))
466                 redo = true;
467         
468         if (fl_get_button(class_->radio_doc_columns_two))
469                 params.columns = 2;
470         else
471                 params.columns = 1;
472         if (fl_get_button(class_->radio_doc_sides_two))
473                 params.sides = LyXTextClass::TwoSides;
474         else
475                 params.sides = LyXTextClass::OneSide;
476         
477         Spacing tmpSpacing = params.spacing;
478         switch (fl_get_choice(class_->choice_doc_spacing)) {
479         case 1:
480                 lyxerr[Debug::INFO] << "Spacing: SINGLE\n";
481                 params.spacing.set(Spacing::Single);
482                 break;
483         case 2:
484                 lyxerr[Debug::INFO] << "Spacing: ONEHALF\n";
485                 params.spacing.set(Spacing::Onehalf);
486                 break;
487         case 3:
488                 lyxerr[Debug::INFO] << "Spacing: DOUBLE\n";
489                 params.spacing.set(Spacing::Double);
490                 break;
491         case 4:
492                 lyxerr[Debug::INFO] << "Spacing: OTHER\n";
493                 params.spacing.set(Spacing::Other, 
494                                    fl_get_input(class_->input_doc_spacing));
495                 break;
496         }
497         if (tmpSpacing != params.spacing)
498                 redo = true;
499         
500         params.options = fl_get_input(class_->input_doc_extra);
501         
502         return redo;
503 }
504
505
506 void FormDocument::paper_apply()
507 {
508     BufferParams & params = lv_->buffer()->params;
509     
510     params.papersize2 =
511             static_cast<char>(fl_get_choice(paper_->choice_papersize2)-1);
512     params.paperpackage =
513             static_cast<char>(fl_get_choice(paper_->choice_paperpackage)-1);
514     params.use_geometry = fl_get_button(paper_->push_use_geometry);
515     if (fl_get_button(paper_->radio_landscape))
516         params.orientation = BufferParams::ORIENTATION_LANDSCAPE;
517     else
518         params.orientation = BufferParams::ORIENTATION_PORTRAIT;
519     params.paperwidth = fl_get_input(paper_->input_custom_width);
520     params.paperheight = fl_get_input(paper_->input_custom_height);
521     params.leftmargin = fl_get_input(paper_->input_left_margin);
522     params.topmargin = fl_get_input(paper_->input_top_margin);
523     params.rightmargin = fl_get_input(paper_->input_right_margin);
524     params.bottommargin = fl_get_input(paper_->input_bottom_margin);
525     params.headheight = fl_get_input(paper_->input_head_height);
526     params.headsep = fl_get_input(paper_->input_head_sep);
527     params.footskip = fl_get_input(paper_->input_foot_skip);
528     lv_->buffer()->setPaperStuff();
529 }
530
531
532 bool FormDocument::language_apply()
533 {
534     BufferParams & params = lv_->buffer()->params;
535     InsetQuotes::quote_language lga = InsetQuotes::EnglishQ;
536     bool redo = false;
537
538     switch (fl_get_choice(language_->choice_quotes_language) - 1) {
539     case 0:
540         lga = InsetQuotes::EnglishQ;
541         break;
542     case 1:
543         lga = InsetQuotes::SwedishQ;
544         break;
545     case 2:
546         lga = InsetQuotes::GermanQ;
547         break;
548     case 3:
549         lga = InsetQuotes::PolishQ;
550                 break;
551     case 4:
552         lga = InsetQuotes::FrenchQ;
553         break;
554     case 5:
555         lga = InsetQuotes::DanishQ;
556         break;
557     }
558     params.quotes_language = lga;
559     if (fl_get_button(language_->radio_single))   
560         params.quotes_times = InsetQuotes::SingleQ;
561     else
562         params.quotes_times = InsetQuotes::DoubleQ;
563
564     Language const * old_language = params.language;
565     Language const * new_language = 
566             languages.getLanguage(combo_language->getline());
567     if (!new_language)
568         new_language = default_language;
569
570     if (old_language != new_language
571         && old_language->RightToLeft() == new_language->RightToLeft()
572         && !lv_->buffer()->isMultiLingual())
573         lv_->buffer()->ChangeLanguage(old_language, new_language);
574     if (old_language != new_language) {
575         redo = true;
576     }
577     params.language = new_language;
578     params.inputenc = fl_get_choice_text(language_->choice_inputenc);
579
580     return redo;
581 }
582
583
584 bool FormDocument::options_apply()
585 {
586     BufferParams & params = lv_->buffer()->params;
587     bool redo = false;
588
589     params.graphicsDriver =
590         fl_get_choice_text(options_->choice_postscript_driver);
591     params.use_amsmath = fl_get_button(options_->check_use_amsmath);
592
593     int tmpchar = int(fl_get_counter_value(options_->slider_secnumdepth));
594     if (params.secnumdepth != tmpchar)
595         redo = true;
596     params.secnumdepth = tmpchar;
597    
598     params.tocdepth = int(fl_get_counter_value(options_->slider_tocdepth));
599
600     params.float_placement =
601         fl_get_input(options_->input_float_placement);
602
603     return redo;
604 }
605
606
607 void FormDocument::bullets_apply()
608 {
609     /* update the bullet settings */
610     BufferParams & param = lv_->buffer()->params;
611     
612     // a little bit of loop unrolling
613     param.user_defined_bullets[0] = param.temp_bullets[0];
614     param.user_defined_bullets[1] = param.temp_bullets[1];
615     param.user_defined_bullets[2] = param.temp_bullets[2];
616     param.user_defined_bullets[3] = param.temp_bullets[3];
617 }
618
619
620 void FormDocument::class_update(BufferParams const & params)
621 {
622     if (!class_.get())
623         return;
624
625     LyXTextClass const & tclass = textclasslist.TextClass(params.textclass);
626
627 #ifdef USE_CLASS_COMBO
628     combo_doc_class->select_text(
629         textclasslist.DescOfClass(params.textclass));
630 #else   
631     fl_set_choice_text(class_->choice_doc_class, 
632                        textclasslist.DescOfClass(params.textclass).c_str());
633 #endif
634     fl_set_choice_text(class_->choice_doc_fonts, params.fonts.c_str());
635     fl_clear_choice(class_->choice_doc_fontsize);
636     fl_addto_choice(class_->choice_doc_fontsize, "default");
637     fl_addto_choice(class_->choice_doc_fontsize,
638                     tclass.opt_fontsize().c_str());
639     fl_set_choice(class_->choice_doc_fontsize,
640                   tokenPos(tclass.opt_fontsize(), '|', params.fontsize)+2);
641     fl_clear_choice(class_->choice_doc_pagestyle);
642     fl_addto_choice(class_->choice_doc_pagestyle, "default");
643     fl_addto_choice(class_->choice_doc_pagestyle,
644                     tclass.opt_pagestyle().c_str());
645     fl_set_choice(class_->choice_doc_pagestyle,
646                   tokenPos(tclass.opt_pagestyle(), '|', params.pagestyle)+2);
647     fl_set_button(class_->radio_doc_indent, 0);
648     fl_set_button(class_->radio_doc_skip, 0);
649     if (params.paragraph_separation == BufferParams::PARSEP_INDENT)
650         fl_set_button(class_->radio_doc_indent, 1);
651     else
652         fl_set_button(class_->radio_doc_skip, 1);
653     switch (params.getDefSkip().kind()) {
654     case VSpace::SMALLSKIP: 
655         fl_set_choice (class_->choice_doc_skip, 1);
656         break;
657     case VSpace::MEDSKIP: 
658         fl_set_choice (class_->choice_doc_skip, 2);
659         break;
660     case VSpace::BIGSKIP: 
661         fl_set_choice (class_->choice_doc_skip, 3);
662         break;
663     case VSpace::LENGTH: 
664         fl_set_choice (class_->choice_doc_skip, 4);
665         fl_set_input (class_->input_doc_skip,
666                       params.getDefSkip().asLyXCommand().c_str());
667         break;
668     default:
669         fl_set_choice (class_->choice_doc_skip, 2);
670         break;
671     }
672     fl_set_button(class_->radio_doc_sides_one, 0);
673     fl_set_button(class_->radio_doc_sides_two, 0);
674     if (params.sides == LyXTextClass::TwoSides)
675         fl_set_button(class_->radio_doc_sides_two, 1);
676     else
677         fl_set_button(class_->radio_doc_sides_one, 1);
678     fl_set_button(class_->radio_doc_columns_one, 0);
679     fl_set_button(class_->radio_doc_columns_two, 0);
680     if (params.columns == 2)
681         fl_set_button(class_->radio_doc_columns_two, 1);
682     else
683         fl_set_button(class_->radio_doc_columns_one, 1);
684     fl_set_input(class_->input_doc_spacing, "");
685     switch (params.spacing.getSpace()) {
686     case Spacing::Default: // nothing bad should happen with this
687     case Spacing::Single:
688         // \singlespacing
689         fl_set_choice(class_->choice_doc_spacing, 1);
690         break;
691     case Spacing::Onehalf:
692         // \onehalfspacing
693         fl_set_choice(class_->choice_doc_spacing, 2);
694         break;
695     case Spacing::Double:
696         // \doublespacing
697         fl_set_choice(class_->choice_doc_spacing, 3);
698         break;
699     case Spacing::Other:
700         {
701             fl_set_choice(class_->choice_doc_spacing, 4);
702             char sval[20];
703             sprintf(sval,"%g",params.spacing.getValue()); 
704             fl_set_input(class_->input_doc_spacing, sval);
705             break;
706         }
707     }
708     if (!params.options.empty())
709         fl_set_input(class_->input_doc_extra, params.options.c_str());
710     else
711         fl_set_input(class_->input_doc_extra, "");
712 }
713
714
715 void FormDocument::language_update(BufferParams const & params)
716 {
717     if (!language_.get())
718         return;
719
720     combo_language->select_text(params.language->lang());
721     fl_set_choice_text(language_->choice_inputenc, params.inputenc.c_str());
722     fl_set_choice(language_->choice_quotes_language, params.quotes_language + 1);
723     fl_set_button(language_->radio_single, 0);
724     fl_set_button(language_->radio_double, 0);
725     if (params.quotes_times == InsetQuotes::SingleQ)
726         fl_set_button(language_->radio_single, 1);
727     else
728         fl_set_button(language_->radio_double, 1);
729 }
730
731
732 void FormDocument::options_update(BufferParams const & params)
733 {
734     if (!options_.get())
735         return;
736
737     fl_set_choice_text(options_->choice_postscript_driver,
738                        params.graphicsDriver.c_str());
739     fl_set_button(options_->check_use_amsmath, params.use_amsmath);
740     fl_set_counter_value(options_->slider_secnumdepth, params.secnumdepth);
741     fl_set_counter_value(options_->slider_tocdepth, params.tocdepth);
742     if (!params.float_placement.empty())
743         fl_set_input(options_->input_float_placement,
744                      params.float_placement.c_str());
745     else
746         fl_set_input(options_->input_float_placement, "");
747 }
748
749
750 void FormDocument::paper_update(BufferParams const & params)
751 {
752     if (!paper_.get())
753         return;
754
755     fl_set_choice(paper_->choice_papersize2, params.papersize2 + 1);
756     fl_set_choice(paper_->choice_paperpackage, params.paperpackage + 1);
757     fl_set_button(paper_->push_use_geometry, params.use_geometry);
758     fl_set_button(paper_->radio_portrait, 0);
759     fl_set_button(paper_->radio_landscape, 0);
760     if (params.orientation == BufferParams::ORIENTATION_LANDSCAPE)
761         fl_set_button(paper_->radio_landscape, 1);
762     else
763         fl_set_button(paper_->radio_portrait, 1);
764     fl_set_input(paper_->input_custom_width, params.paperwidth.c_str());
765     fl_set_input(paper_->input_custom_height, params.paperheight.c_str());
766     fl_set_input(paper_->input_left_margin, params.leftmargin.c_str());
767     fl_set_input(paper_->input_top_margin, params.topmargin.c_str());
768     fl_set_input(paper_->input_right_margin, params.rightmargin.c_str());
769     fl_set_input(paper_->input_bottom_margin, params.bottommargin.c_str());
770     fl_set_input(paper_->input_head_height, params.headheight.c_str());
771     fl_set_input(paper_->input_head_sep, params.headsep.c_str());
772     fl_set_input(paper_->input_foot_skip, params.footskip.c_str());
773     fl_set_focus_object(paper_->form, paper_->choice_papersize2);
774 }
775
776
777 void FormDocument::bullets_update(BufferParams const & params)
778 {
779     if (!bullets_.get() || ((XpmVersion<4) || (XpmVersion==4 && XpmRevision<7)))
780         return;
781
782     bool const isLinuxDoc = lv_->buffer()->isLinuxDoc();
783     setEnabled(fbullet, !isLinuxDoc);
784
785     if (isLinuxDoc) return;
786
787     fl_set_button(bullets_->radio_bullet_depth_1, 1);
788     fl_set_input(bullets_->input_bullet_latex,
789                  params.user_defined_bullets[0].getText().c_str());
790     fl_set_choice(bullets_->choice_bullet_size,
791                   params.user_defined_bullets[0].getSize() + 2);
792 }
793
794
795 void FormDocument::checkReadOnly()
796 {
797     if (bc().readOnly(lv_->buffer()->isReadonly())) {
798         combo_doc_class->deactivate();
799         combo_language->deactivate();
800         fl_set_object_label(dialog_->text_warning,
801                             _("Document is read-only."
802                               " No changes to layout permitted."));
803         fl_show_object(dialog_->text_warning);
804     } else {
805         combo_doc_class->activate();
806         combo_language->activate();
807         fl_hide_object(dialog_->text_warning);
808     }   
809 }
810
811
812 void FormDocument::checkMarginValues()
813 {
814         bool const not_empty =
815                 strlen(fl_get_input(paper_->input_top_margin)) ||
816                 strlen(fl_get_input(paper_->input_bottom_margin)) ||
817                 strlen(fl_get_input(paper_->input_left_margin)) ||
818                 strlen(fl_get_input(paper_->input_right_margin)) ||
819                 strlen(fl_get_input(paper_->input_head_height)) ||
820                 strlen(fl_get_input(paper_->input_head_sep)) ||
821                 strlen(fl_get_input(paper_->input_foot_skip)) ||
822                 strlen(fl_get_input(paper_->input_custom_width)) ||
823                 strlen(fl_get_input(paper_->input_custom_height));
824         if (not_empty)
825                 fl_set_button(paper_->push_use_geometry, 1);
826 }
827
828
829 bool FormDocument::CheckDocumentInput(FL_OBJECT * ob, long)
830 {
831     string str;
832     int val;
833     bool ok = true;
834     char const * input;
835     
836     checkMarginValues();
837     if (ob == paper_->choice_papersize2) {
838         val = fl_get_choice(paper_->choice_papersize2)-1;
839         if (val == BufferParams::VM_PAPER_DEFAULT) {
840             fl_set_button(paper_->push_use_geometry, 0);
841             checkMarginValues();
842         } else {
843             if ((val != BufferParams::VM_PAPER_USLETTER) &&
844                 (val != BufferParams::VM_PAPER_USLEGAL) &&
845                 (val != BufferParams::VM_PAPER_USEXECUTIVE) &&
846                 (val != BufferParams::VM_PAPER_A4) &&
847                 (val != BufferParams::VM_PAPER_A5) &&
848                 (val != BufferParams::VM_PAPER_B5)) {
849                 fl_set_button(paper_->push_use_geometry, 1);
850             }
851             fl_set_choice(paper_->choice_paperpackage,
852                           BufferParams::PACKAGE_NONE + 1);
853         }
854     } else if (ob == paper_->choice_paperpackage) {
855         val = fl_get_choice(paper_->choice_paperpackage)-1;
856         if (val != BufferParams::PACKAGE_NONE) {
857             fl_set_choice(paper_->choice_papersize2,
858                           BufferParams::VM_PAPER_DEFAULT + 1);
859             fl_set_button(paper_->push_use_geometry, 0);
860         }
861     } else if (ob == class_->input_doc_spacing) {
862         input = fl_get_input(class_->input_doc_spacing);
863         if (!*input) {
864             fl_set_choice (class_->choice_doc_spacing, 1);
865         } else {
866             fl_set_choice(class_->choice_doc_spacing, 4);
867         }
868     }
869     // this has to be all out of if/elseif because it has to deactivate
870     // the document buttons and so the whole stuff has to be tested again.
871     str = fl_get_input(paper_->input_custom_width);
872     ok = ok && (str.empty() || isValidLength(str));
873     str = fl_get_input(paper_->input_custom_height);
874     ok = ok && (str.empty() || isValidLength(str));
875     str = fl_get_input(paper_->input_left_margin);
876     ok = ok && (str.empty() || isValidLength(str));
877     str = fl_get_input(paper_->input_right_margin);
878     ok = ok && (str.empty() || isValidLength(str));
879     str = fl_get_input(paper_->input_top_margin);
880     ok = ok && (str.empty() || isValidLength(str));
881     str = fl_get_input(paper_->input_bottom_margin);
882     ok = ok && (str.empty() || isValidLength(str));
883     str = fl_get_input(paper_->input_head_height);
884     ok = ok && (str.empty() || isValidLength(str));
885     str = fl_get_input(paper_->input_head_sep);
886     ok = ok && (str.empty() || isValidLength(str));
887     str = fl_get_input(paper_->input_foot_skip);
888     ok = ok && (str.empty() || isValidLength(str));
889     // "Synchronize" the choice and the input field, so that it
890     // is impossible to commit senseless data.
891     input = fl_get_input (class_->input_doc_skip);
892     if (ob == class_->input_doc_skip) {
893         if (!*input) {
894             fl_set_choice (class_->choice_doc_skip, 2);
895         } else if (isValidGlueLength (input)) {
896             fl_set_choice (class_->choice_doc_skip, 4);
897         } else {
898             fl_set_choice(class_->choice_doc_skip, 4);
899             ok = false;
900         }
901     } else {
902         if (*input && !isValidGlueLength(input))
903             ok = false;
904     }
905     if ((fl_get_choice(class_->choice_doc_skip) == 4) && !*input)
906         ok = false;
907     else if (fl_get_choice(class_->choice_doc_skip) != 4)
908         fl_set_input (class_->input_doc_skip, "");
909
910     input = fl_get_input(class_->input_doc_spacing);
911     if ((fl_get_choice(class_->choice_doc_spacing) == 4) && !*input)
912         ok = false;
913     else  if (fl_get_choice(class_->choice_doc_spacing) != 4)
914         fl_set_input (class_->input_doc_spacing, "");
915     return ok;
916 }
917
918
919 void FormDocument::ChoiceBulletSize(FL_OBJECT * ob, long /*data*/ )
920 {
921     BufferParams & param = lv_->buffer()->params;
922
923     // convert from 1-6 range to -1-4 
924     param.temp_bullets[current_bullet_depth].setSize(fl_get_choice(ob) - 2);
925     fl_set_input(bullets_->input_bullet_latex,
926                  param.temp_bullets[current_bullet_depth].getText().c_str());
927 }
928
929
930 void FormDocument::InputBulletLaTeX(FL_OBJECT *, long)
931 {
932     BufferParams & param = lv_->buffer()->params;
933
934     param.temp_bullets[current_bullet_depth].
935         setText(fl_get_input(bullets_->input_bullet_latex));
936 }
937
938
939 void FormDocument::BulletDepth(FL_OBJECT * ob, State cb)
940 {
941     /* Should I do the following:                                 */
942     /*  1. change to the panel that the current bullet belongs in */
943     /*  2. show that bullet as selected                           */
944     /*  3. change the size setting to the size of the bullet in Q.*/
945     /*  4. display the latex equivalent in the latex box          */
946     /*                                                            */
947     /* I'm inclined to just go with 3 and 4 at the moment and     */
948     /* maybe try to support the others later                      */
949     BufferParams & param = lv_->buffer()->params;
950
951     int data = 0;
952     if (cb == BULLETDEPTH1 )
953             data = 0;
954     else if (cb == BULLETDEPTH2 )
955             data = 1;
956     else if (cb == BULLETDEPTH3 )
957             data = 2;
958     else if (cb == BULLETDEPTH4 )
959             data = 3;
960
961     switch (fl_get_button_numb(ob)) {
962     case 3:
963             // right mouse button resets to default
964         param.temp_bullets[data] = ITEMIZE_DEFAULTS[data];
965     default:
966         current_bullet_depth = data;
967         fl_set_input(bullets_->input_bullet_latex,
968                      param.temp_bullets[data].getText().c_str());
969         fl_set_choice(bullets_->choice_bullet_size,
970                       param.temp_bullets[data].getSize() + 2);
971     }
972 }
973
974
975 void FormDocument::BulletPanel(FL_OBJECT * /*ob*/, State cb)
976 {
977     /* Here we have to change the background pixmap to that selected */
978     /* by the user. (eg. standard.xpm, psnfss1.xpm etc...)           */
979     
980     int data = 0;
981     if (cb == BULLETPANEL1 )
982             data = 0;
983     else if (cb == BULLETPANEL2 )
984             data = 1;
985     else if (cb == BULLETPANEL3 )
986             data = 2;
987     else if (cb == BULLETPANEL4 )
988             data = 3;
989     else if (cb == BULLETPANEL5 )
990             data = 4;
991     else if (cb == BULLETPANEL6 )
992             data = 5;
993
994     if (data != current_bullet_panel) {
995         fl_freeze_form(bullets_->form);
996         current_bullet_panel = data;
997
998         /* free the current pixmap */
999         fl_free_bmtable_pixmap(bullets_->bmtable_bullet_panel);
1000         string new_panel;
1001         switch (cb) {
1002             /* display the new one */
1003         case BULLETPANEL1 :
1004             new_panel = "standard";
1005             break;
1006         case BULLETPANEL2 :
1007             new_panel = "amssymb";
1008             break;
1009         case BULLETPANEL3 :
1010             new_panel = "psnfss1";
1011             break;
1012         case BULLETPANEL4 :
1013             new_panel = "psnfss2";
1014             break;
1015         case BULLETPANEL5 :
1016             new_panel = "psnfss3";
1017             break;
1018         case BULLETPANEL6 :
1019             new_panel = "psnfss4";
1020             break;
1021         default :
1022             /* something very wrong happened */
1023             // play it safe for now but should be an exception
1024             current_bullet_panel = 0;  // standard panel
1025             new_panel = "standard";
1026             break;
1027         }
1028         new_panel += ".xpm";
1029         fl_set_bmtable_pixmap_file(bullets_->bmtable_bullet_panel, 6, 6,
1030                                    LibFileSearch("images", new_panel).c_str());
1031         fl_redraw_object(bullets_->bmtable_bullet_panel);
1032         fl_unfreeze_form(bullets_->form);
1033     }
1034 }
1035
1036
1037 void FormDocument::BulletBMTable(FL_OBJECT * ob, long /*data*/ )
1038 {
1039     /* handle the user input by setting the current bullet depth's pixmap */
1040     /* to that extracted from the current chosen position of the BMTable  */
1041     /* Don't forget to free the button's old pixmap first.                */
1042
1043     BufferParams & param = lv_->buffer()->params;
1044     int bmtable_button = fl_get_bmtable(ob);
1045
1046     /* try to keep the button held down till another is pushed */
1047     /*  fl_set_bmtable(ob, 1, bmtable_button); */
1048     param.temp_bullets[current_bullet_depth].setFont(current_bullet_panel);
1049     param.temp_bullets[current_bullet_depth].setCharacter(bmtable_button);
1050     fl_set_input(bullets_->input_bullet_latex,
1051                  param.temp_bullets[current_bullet_depth].getText().c_str());
1052 }
1053
1054
1055 void FormDocument::CheckChoiceClass(FL_OBJECT * ob, long)
1056 {
1057     if (!ob)
1058         ob = class_->choice_doc_class;
1059
1060     ProhibitInput(lv_->view());
1061
1062 #ifdef USE_CLASS_COMBO
1063     unsigned int tc = combo_doc_class->get() - 1;
1064     string tct = combo_doc_class->getline();
1065 #else
1066     int tc = fl_get_choice(ob) - 1;
1067     string tct = fl_get_choice_text(ob);
1068 #endif
1069     if (textclasslist.Load(tc)) {
1070             // we use a copy of the bufferparams because we do not
1071             // want to modify them yet. 
1072             BufferParams params = lv_->buffer()->params;
1073
1074             if (params.textclass != tc
1075                 && AskQuestion(_("Should I set some parameters to"), 
1076                                _("the defaults of this document class?"))) {
1077             params.textclass = tc;
1078             params.useClassDefaults();
1079             UpdateLayoutDocument(params);
1080         }
1081     } else {
1082         // unable to load new style
1083         WriteAlert(_("Conversion Errors!"),
1084                    _("Unable to switch to new document class."),
1085                    _("Reverting to original document class."));
1086 #ifdef USE_CLASS_COMBO
1087         combo_doc_class->select(int(lv_->buffer()->params.textclass) + 1);
1088 #else
1089         fl_set_choice(class_->choice_doc_class, 
1090                       lv_->buffer()->params.textclass + 1);
1091 #endif
1092     }
1093     AllowInput(lv_->view());
1094 }
1095
1096
1097 void FormDocument::UpdateLayoutDocument(BufferParams const & params)
1098 {
1099     if (!dialog_.get())
1100         return;
1101
1102     checkReadOnly();
1103     class_update(params);
1104     paper_update(params);
1105     language_update(params);
1106     options_update(params);
1107     bullets_update(params);
1108 }