]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormDocument.C
Yet more dialog tweaking from Rob.
[lyx.git] / src / frontends / xforms / FormDocument.C
1 /**
2  * \file FormDocument.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Jürgen Vigna
7  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #include FORMS_H_LOCATION
14 #include XPM_H_LOCATION
15
16 #ifdef __GNUG__
17 #pragma implementation
18 #endif
19
20 #include "FormDocument.h"
21 #include "forms/form_document.h"
22 #include "Alert.h"
23 #include "lyxtextclasslist.h"
24 #include "combox.h"
25 #include "tex-strings.h"
26 #include "bufferparams.h"
27 #include "vspace.h"
28 #include "bmtable.h"
29 #include "language.h"
30 #include "frnt_lang.h"
31 #include "frontends/LyXView.h"
32 #include "lyxfunc.h"
33 #include "lyxrc.h"
34 #include "BufferView.h"
35 #include "buffer.h"
36 #include "Liason.h"
37 #include "CutAndPaste.h"
38 #include "bufferview_funcs.h"
39 #include "xforms_helpers.h"
40 #include "debug.h"
41 #include "input_validators.h" // fl_unsigned_float_filter
42 #include "helper_funcs.h"
43 #include "lyx_main.h" // for user_lyxdir
44
45 #include "insets/insetquotes.h"
46
47 #include "support/filetools.h"
48 #include "support/lstrings.h"
49
50 #include FORMS_H_LOCATION
51
52 #include <boost/bind.hpp>
53
54 #include <functional>
55
56 using std::bind2nd;
57
58 using Liason::setMinibuffer;
59 using std::vector;
60
61 FormDocument::FormDocument(LyXView & lv, Dialogs & d)
62         : FormBaseBD(lv, d, _("Document Layout")),
63           ActCell(0), Confirmed(0),
64           current_bullet_panel(0), current_bullet_depth(0), fbullet(0)
65 {
66 }
67
68
69 void FormDocument::redraw()
70 {
71         if (form() && form()->visible)
72                 fl_redraw_form(form());
73         else
74                 return;
75
76         FL_FORM * outer_form = fl_get_active_folder(dialog_->tabfolder);
77         if (outer_form && outer_form->visible)
78                 fl_redraw_form(outer_form);
79 }
80
81
82 FL_FORM * FormDocument::form() const
83 {
84         if (dialog_.get()) return dialog_->form;
85         return 0;
86 }
87
88
89 void FormDocument::build()
90 {
91         int n;
92
93         // the tabbed folder
94         dialog_.reset(build_document(this));
95
96         // Allow the base class to control messages
97         setMessageWidget(dialog_->text_warning);
98
99         // Manage the restore, ok, apply, restore and cancel/close buttons
100         bc().setOK(dialog_->button_ok);
101         bc().setApply(dialog_->button_apply);
102         bc().setCancel(dialog_->button_close);
103         bc().setRestore(dialog_->button_restore);
104         bc().addReadOnly (dialog_->button_save_defaults);
105         bc().addReadOnly (dialog_->button_reset_defaults);
106
107         // the document paper form
108         paper_.reset(build_document_paper(this));
109         fl_addto_choice(paper_->choice_papersize,
110                         _(" Default | Custom | US letter | US legal "
111                           "| US executive | A3 | A4 | A5 | B3 | B4 | B5 "));
112         fl_addto_choice(paper_->choice_paperpackage,
113                         _(" None "
114                           "| Small Margins "
115                           "| Very small Margins "
116                           "| Very wide Margins "));
117
118         fl_set_input_return(paper_->input_custom_width,  FL_RETURN_CHANGED);
119         fl_set_input_return(paper_->input_custom_height, FL_RETURN_CHANGED);
120         fl_set_input_return(paper_->input_top_margin,    FL_RETURN_CHANGED);
121         fl_set_input_return(paper_->input_bottom_margin, FL_RETURN_CHANGED);
122         fl_set_input_return(paper_->input_inner_margin,  FL_RETURN_CHANGED);
123         fl_set_input_return(paper_->input_outer_margin,  FL_RETURN_CHANGED);
124         fl_set_input_return(paper_->input_head_height,   FL_RETURN_CHANGED);
125         fl_set_input_return(paper_->input_head_sep,      FL_RETURN_CHANGED);
126         fl_set_input_return(paper_->input_foot_skip,     FL_RETURN_CHANGED);
127
128         setPrehandler(paper_->input_custom_width);
129         setPrehandler(paper_->input_custom_height);
130         setPrehandler(paper_->input_top_margin);
131         setPrehandler(paper_->input_bottom_margin);
132         setPrehandler(paper_->input_inner_margin);
133         setPrehandler(paper_->input_outer_margin);
134         setPrehandler(paper_->input_head_height);
135         setPrehandler(paper_->input_head_sep);
136         setPrehandler(paper_->input_foot_skip);
137
138         // Create the contents of the unit choices
139         // Don't include the "%" terms...
140         vector<string> units_vec = getLatexUnits();
141         vector<string>::iterator ret =
142                 std::remove_if(units_vec.begin(),
143                                units_vec.end(),
144                                bind2nd(contains_functor(), "%"));
145         units_vec.erase(ret, units_vec.end());
146
147         string units = getStringFromVector(units_vec, "|");
148
149         fl_addto_choice(paper_->choice_custom_width_units,  units.c_str());
150         fl_addto_choice(paper_->choice_custom_height_units, units.c_str());
151         fl_addto_choice(paper_->choice_top_margin_units,    units.c_str());
152         fl_addto_choice(paper_->choice_bottom_margin_units, units.c_str());
153         fl_addto_choice(paper_->choice_inner_margin_units,  units.c_str());
154         fl_addto_choice(paper_->choice_outer_margin_units,  units.c_str());
155         fl_addto_choice(paper_->choice_head_height_units,   units.c_str());
156         fl_addto_choice(paper_->choice_head_sep_units,      units.c_str());
157         fl_addto_choice(paper_->choice_foot_skip_units,     units.c_str());
158
159         bc().addReadOnly (paper_->choice_paperpackage);
160         bc().addReadOnly (paper_->radio_portrait);
161         bc().addReadOnly (paper_->radio_landscape);
162         bc().addReadOnly (paper_->choice_papersize);
163         bc().addReadOnly (paper_->check_use_geometry);
164         bc().addReadOnly (paper_->input_custom_width);
165         bc().addReadOnly (paper_->input_custom_height);
166         bc().addReadOnly (paper_->input_top_margin);
167         bc().addReadOnly (paper_->input_bottom_margin);
168         bc().addReadOnly (paper_->input_inner_margin);
169         bc().addReadOnly (paper_->input_outer_margin);
170         bc().addReadOnly (paper_->input_head_height);
171         bc().addReadOnly (paper_->input_head_sep);
172         bc().addReadOnly (paper_->input_foot_skip);
173
174         // the document class form
175         class_.reset(build_document_class(this));
176
177         FL_OBJECT * obj;
178         // The language is a combo-box and has to be inserted manually
179         obj = class_->choice_doc_class;
180         fl_deactivate_object(obj);
181         fl_addto_form(class_->form);
182         combo_doc_class.reset(new Combox(FL_COMBOX_DROPLIST));
183         combo_doc_class->add(obj->x, obj->y, obj->w, obj->h, 400,
184                              dialog_->tabfolder);
185         combo_doc_class->shortcut("#C",1);
186         combo_doc_class->setcallback(ComboInputCB, this);
187         fl_end_form();
188         for (LyXTextClassList::const_iterator cit = textclasslist.begin();
189              cit != textclasslist.end(); ++cit) {
190                 combo_doc_class->addto(cit->description());
191         }
192
193         fl_addto_choice(class_->choice_doc_spacing,
194                         _(" Single | OneHalf | Double | Custom "));
195         fl_addto_choice(class_->choice_doc_fontsize, "default|10|11|12");
196         for (n=0; tex_fonts[n][0]; ++n) {
197                 fl_addto_choice(class_->choice_doc_fonts,tex_fonts[n]);
198         }
199         fl_addto_choice(class_->choice_doc_pagestyle,
200                         "default|empty|plain|headings|fancy");
201         fl_addto_choice(class_->choice_doc_skip,
202                         _(" Smallskip | Medskip | Bigskip | Length "));
203         fl_addto_choice(class_->choice_default_skip_units,  units.c_str());
204         fl_set_input_return(class_->input_doc_extra, FL_RETURN_CHANGED);
205         fl_set_input_return(class_->input_doc_skip, FL_RETURN_CHANGED);
206         fl_set_input_return(class_->input_doc_spacing, FL_RETURN_CHANGED);
207
208         setPrehandler(class_->input_doc_extra);
209         setPrehandler(class_->input_doc_skip);
210         setPrehandler(class_->input_doc_spacing);
211
212         // Set input filters on doc spacing to make it accept only
213         // unsigned numbers.
214         fl_set_input_filter(class_->input_doc_spacing, fl_unsigned_float_filter);
215
216         bc().addReadOnly (class_->radio_doc_indent);
217         bc().addReadOnly (class_->radio_doc_skip);
218
219         bc().addReadOnly (class_->choice_doc_pagestyle);
220         bc().addReadOnly (class_->choice_doc_fonts);
221         bc().addReadOnly (class_->choice_doc_fontsize);
222         bc().addReadOnly (class_->radio_doc_sides_one);
223         bc().addReadOnly (class_->radio_doc_sides_two);
224         bc().addReadOnly (class_->radio_doc_columns_one);
225         bc().addReadOnly (class_->radio_doc_columns_two);
226         bc().addReadOnly (class_->input_doc_extra);
227         bc().addReadOnly (class_->input_doc_skip);
228         bc().addReadOnly (class_->choice_doc_skip);
229         bc().addReadOnly (class_->choice_doc_spacing);
230         bc().addReadOnly (class_->input_doc_spacing);
231
232         // the document language form
233         language_.reset(build_document_language(this));
234         fl_addto_choice(language_->choice_inputenc,
235                         "default|auto|latin1|latin2|latin3|latin4|latin5|latin9"
236                         "|koi8-r|koi8-u|cp866|cp1251|iso88595|pt154");
237
238         vector<frnt::LanguagePair> const langs = frnt::getLanguageData(false);
239         // Store the identifiers for later
240         lang_ = getSecond(langs);
241
242         // The language is a combo-box and has to be inserted manually
243         obj = language_->choice_language;
244         fl_deactivate_object(obj);
245         fl_addto_form(language_->form);
246         combo_language.reset(new Combox(FL_COMBOX_DROPLIST));
247         combo_language->add(obj->x, obj->y, obj->w, obj->h, 400,
248                             dialog_->tabfolder);
249         combo_language->shortcut("#L",1);
250         combo_language->setcallback(ComboInputCB, this);
251         fl_end_form();
252
253         vector<frnt::LanguagePair>::const_iterator lit  = langs.begin();
254         vector<frnt::LanguagePair>::const_iterator lend = langs.end();
255         for (; lit != lend; ++lit) {
256                 combo_language->addto(lit->first);
257         }
258         combo_language->select(1);
259
260         fl_addto_choice(language_->choice_quotes_language,
261                         _(" ``text'' | ''text'' | ,,text`` | ,,text'' |"
262                           " «text» | »text« "));
263
264         bc().addReadOnly (language_->choice_inputenc);
265         bc().addReadOnly (language_->choice_quotes_language);
266         bc().addReadOnly (language_->radio_single);
267         bc().addReadOnly (language_->radio_double);
268
269         // the document options form
270         options_.reset(build_document_options(this));
271         fl_set_input_return(options_->input_float_placement, FL_RETURN_CHANGED);
272         setPrehandler(options_->input_float_placement);
273
274         fl_set_counter_bounds(options_->counter_secnumdepth,-2,5);
275         fl_set_counter_bounds(options_->counter_tocdepth,-1,5);
276         fl_set_counter_step(options_->counter_secnumdepth,1,1);
277         fl_set_counter_step(options_->counter_tocdepth,1,1);
278         fl_set_counter_precision(options_->counter_secnumdepth, 0);
279         fl_set_counter_precision(options_->counter_tocdepth, 0);
280         for (n=0; tex_graphics[n][0]; ++n) {
281                 fl_addto_choice(options_->choice_postscript_driver,
282                                 tex_graphics[n]);
283         }
284         fl_addto_choice(options_->choice_citation_format,
285                         _(" Author-year | Numerical "));
286
287         bc_.addReadOnly (options_->counter_secnumdepth);
288         bc_.addReadOnly (options_->counter_tocdepth);
289         bc_.addReadOnly (options_->check_use_amsmath);
290         bc_.addReadOnly (options_->check_use_natbib);
291         bc_.addReadOnly (options_->choice_citation_format);
292         bc_.addReadOnly (options_->input_float_placement);
293         bc_.addReadOnly (options_->choice_postscript_driver);
294
295         // the document bullets form
296         bullets_.reset(build_document_bullet(this));
297         fl_addto_choice(bullets_->choice_bullet_size,
298                         _(" default | tiny | script | footnote | small |"
299                           " normal | large | Large | LARGE | huge | Huge"));
300         fl_set_choice(bullets_->choice_bullet_size, 1);
301         fl_set_input_return(bullets_->input_bullet_latex, FL_RETURN_CHANGED);
302         setPrehandler(bullets_->input_bullet_latex);
303         fl_set_input_maxchars(bullets_->input_bullet_latex, 80);
304
305         string const bmtablefile = LibFileSearch("images", "standard", "xpm");
306         fl_set_bmtable_pixmap_file(bullets_->bmtable_bullet_panel, 6, 6,
307                                    bmtablefile.c_str());
308
309         bc_.addReadOnly(bullets_->radio_bullet_depth_1);
310         bc_.addReadOnly(bullets_->radio_bullet_depth_2);
311         bc_.addReadOnly(bullets_->radio_bullet_depth_3);
312         bc_.addReadOnly(bullets_->radio_bullet_depth_4);
313         bc_.addReadOnly(bullets_->radio_bullet_panel_standard);
314         bc_.addReadOnly(bullets_->radio_bullet_panel_maths);
315         bc_.addReadOnly(bullets_->radio_bullet_panel_ding1);
316         bc_.addReadOnly(bullets_->radio_bullet_panel_ding2);
317         bc_.addReadOnly(bullets_->radio_bullet_panel_ding3);
318         bc_.addReadOnly(bullets_->radio_bullet_panel_ding4);
319
320         bc().addReadOnly (bullets_->bmtable_bullet_panel);
321         bc().addReadOnly (bullets_->choice_bullet_size);
322         bc().addReadOnly (bullets_->input_bullet_latex);
323
324         fl_addto_tabfolder(dialog_->tabfolder,_("Document"),
325                            class_->form);
326         fl_addto_tabfolder(dialog_->tabfolder,_("Paper"),
327                            paper_->form);
328         fl_addto_tabfolder(dialog_->tabfolder,_("Language"),
329                            language_->form);
330         fl_addto_tabfolder(dialog_->tabfolder,_("Extra"),
331                            options_->form);
332         fbullet = fl_addto_tabfolder(dialog_->tabfolder,_("Bullets"),
333                                      bullets_->form);
334         if ((XpmVersion < 4) || (XpmVersion == 4 && XpmRevision < 7)) {
335                 lyxerr << _("Your version of libXpm is older than 4.7.\n"
336                             "The `bullet' tab of the document dialog "
337                             "has been disabled") << '\n';
338                 fl_deactivate_object(fbullet);
339                 fl_set_object_lcol(fbullet, FL_INACTIVE);
340         }
341 }
342
343
344 void FormDocument::apply()
345 {
346         if (!lv_.view()->available() || !dialog_.get())
347                 return;
348
349         bool redo = class_apply();
350         paper_apply();
351         redo = language_apply() || redo;
352         redo = options_apply() || redo;
353         bullets_apply();
354
355         if (redo) {
356                 lv_.view()->redoCurrentBuffer();
357         }
358         lv_.buffer()->markDirty();
359         setMinibuffer(&lv_, _("Document layout set"));
360 }
361
362
363 void FormDocument::cancel()
364 {
365         // this avoids confusion when reopening
366         BufferParams & param = lv_.buffer()->params;
367         param.temp_bullets[0] = param.user_defined_bullets[0];
368         param.temp_bullets[1] = param.user_defined_bullets[1];
369         param.temp_bullets[2] = param.user_defined_bullets[2];
370         param.temp_bullets[3] = param.user_defined_bullets[3];
371         hide();
372 }
373
374
375 void FormDocument::update()
376 {
377         if (!dialog_.get())
378                 return;
379
380         checkReadOnly();
381
382         BufferParams const & params = lv_.buffer()->params;
383
384         class_update(params);
385         paper_update(params);
386         language_update(params);
387         options_update(params);
388         bullets_update(params);
389 }
390
391
392 namespace {
393 // should this go elsewhere? Maybe a ControllerDocument? (JMarc)
394 /** Save the buffer's parameters as user default.
395     This function saves a file \c user_lyxdir/templates/defaults.lyx
396     which parameters are those of the current buffer. This file
397     is used as a default template when creating a new
398     file. Returns \c true on success.
399 */
400 bool saveParamsAsDefault(BufferParams const &params)
401 {
402         if (!Alert::askQuestion(_("Do you want to save the current settings"),
403                                 _("for the document layout as default?"),
404                                 _("(they will be valid for any new document)")))
405                 return false;
406
407         string const fname = AddName(AddPath(user_lyxdir, "templates/"),
408                                      "defaults.lyx");
409         Buffer defaults(fname);
410         defaults.params = params;
411
412         // add an empty paragraph. Is this enough?
413         defaults.paragraphs.set(new Paragraph);
414
415         return defaults.writeFile(defaults.fileName());
416 }
417
418 } //namespace
419
420
421 bool FormDocument::input(FL_OBJECT * ob, long)
422 {
423         if (ob == class_->choice_doc_class) {
424                 CheckChoiceClass(ob, 0);
425         } else if (ob == bullets_->choice_bullet_size) {
426                 ChoiceBulletSize(ob, 0);
427         } else if (ob == bullets_->input_bullet_latex) {
428                 InputBulletLaTeX(ob, 0);
429         } else if (ob == bullets_->radio_bullet_depth_1 ||
430                    ob == bullets_->radio_bullet_depth_2 ||
431                    ob == bullets_->radio_bullet_depth_3 ||
432                    ob == bullets_->radio_bullet_depth_4) {
433                 BulletDepth(ob);
434         } else if (ob == bullets_->radio_bullet_panel_standard ||
435                    ob == bullets_->radio_bullet_panel_maths ||
436                    ob == bullets_->radio_bullet_panel_ding1 ||
437                    ob == bullets_->radio_bullet_panel_ding2 ||
438                    ob == bullets_->radio_bullet_panel_ding3 ||
439                    ob == bullets_->radio_bullet_panel_ding4) {
440                 BulletPanel(ob);
441         } else if (ob == bullets_->bmtable_bullet_panel) {
442                 BulletBMTable(ob, 0);
443         }
444
445         bool const length_input = fl_get_choice(class_->choice_doc_skip) == 4;
446         if (ob == class_->choice_doc_skip) {
447                 setEnabled(class_->input_doc_skip, length_input);
448                 setEnabled(class_->choice_default_skip_units, length_input);
449         }
450
451         if (ob == class_->choice_doc_spacing)
452                 setEnabled(class_->input_doc_spacing,
453                            fl_get_choice(class_->choice_doc_spacing) == 4);
454
455         bool const skip_used = fl_get_button(class_->radio_doc_skip);
456         if (ob == class_->radio_doc_skip ||
457             ob == class_->radio_doc_indent) {
458                 setEnabled(class_->choice_doc_skip, skip_used);
459                 setEnabled(class_->input_doc_skip,
460                            skip_used && length_input);
461                 setEnabled(class_->choice_default_skip_units,
462                            skip_used && length_input);
463                 // Default unit choice is cm if metric, inches if US paper.
464                 // If papersize is default, check the lyxrc-settings
465                 int const paperchoice = fl_get_choice(paper_->choice_papersize);
466                 bool const metric = (paperchoice == 1 && lyxrc.default_papersize > 3)
467                         || paperchoice == 2 || paperchoice > 5;
468                 int const default_unit = metric ? 8 : 9;
469                 if (rtrim(fl_get_input(class_->input_doc_skip)).empty())
470                         fl_set_choice(class_->choice_default_skip_units,
471                                       default_unit);
472         }
473
474         if (ob == options_->check_use_natbib) {
475                 setEnabled(options_->choice_citation_format,
476                            fl_get_button(options_->check_use_natbib));
477         }
478
479         if (ob == dialog_->button_save_defaults) {
480                 BufferParams params;
481                 class_apply(params);
482                 paper_apply(params);
483                 language_apply(params);
484                 options_apply(params);
485                 bullets_apply(params);
486                 params.preamble = lv_.buffer()->params.preamble;
487                 saveParamsAsDefault(params);
488         }
489
490         if (ob == dialog_->button_reset_defaults) {
491                 BufferParams params = lv_.buffer()->params;
492                 params.textclass = combo_doc_class->get() - 1;
493                 params.useClassDefaults();
494                 UpdateLayoutDocument(params);
495         }
496
497         if (ob == paper_->radio_landscape)
498                 fl_set_choice(paper_->choice_paperpackage,
499                               BufferParams::PACKAGE_NONE + 1);
500
501         if (ob == paper_->choice_papersize) {
502                 int const paperchoice = fl_get_choice(paper_->choice_papersize);
503                 bool const defsize = paperchoice == 1;
504                 bool const custom = paperchoice == 2;
505                 bool const a3size = paperchoice == 6;
506                 bool const b3size = paperchoice == 9;
507                 bool const b4size = paperchoice == 10;
508
509                 if (custom)
510                         fl_set_button(paper_->radio_portrait, 1);
511
512                 bool const use_geom = (custom || a3size || b3size || b4size);
513
514                 fl_set_button(paper_->check_use_geometry, int(use_geom));
515
516                 setEnabled(paper_->input_top_margin,    use_geom);
517                 setEnabled(paper_->input_bottom_margin, use_geom);
518                 setEnabled(paper_->input_inner_margin,  use_geom);
519                 setEnabled(paper_->input_outer_margin,  use_geom);
520                 setEnabled(paper_->input_head_height,   use_geom);
521                 setEnabled(paper_->input_head_sep,      use_geom);
522                 setEnabled(paper_->input_foot_skip,     use_geom);
523                 setEnabled(paper_->choice_top_margin_units,    use_geom);
524                 setEnabled(paper_->choice_bottom_margin_units, use_geom);
525                 setEnabled(paper_->choice_inner_margin_units,  use_geom);
526                 setEnabled(paper_->choice_outer_margin_units,  use_geom);
527                 setEnabled(paper_->choice_head_height_units,   use_geom);
528                 setEnabled(paper_->choice_head_sep_units,      use_geom);
529                 setEnabled(paper_->choice_foot_skip_units,     use_geom);
530                 setEnabled(paper_->choice_custom_width_units,  use_geom);
531                 setEnabled(paper_->choice_custom_height_units, use_geom);
532
533                 setEnabled(paper_->input_custom_width,  custom);
534                 setEnabled(paper_->input_custom_height, custom);
535                 setEnabled(paper_->choice_custom_width_units,  custom);
536                 setEnabled(paper_->choice_custom_height_units, custom);
537                 setEnabled(paper_->radio_portrait,  !custom);
538                 setEnabled(paper_->radio_landscape, !custom);
539
540                 // Default unit choice is cm if metric, inches if US paper.
541                 // If papersize is default, use the lyxrc-settings
542                 bool const metric = (defsize && lyxrc.default_papersize > 3)
543                         || paperchoice == 2 || paperchoice > 5;
544                 int const default_unit = metric ? 8 : 9;
545                 if (rtrim(fl_get_input(paper_->input_custom_width)).empty())
546                         fl_set_choice(paper_->choice_custom_width_units,
547                                       default_unit);
548                 if (rtrim(fl_get_input(paper_->input_custom_height)).empty())
549                         fl_set_choice(paper_->choice_custom_height_units,
550                                       default_unit);
551                 if (rtrim(fl_get_input(paper_->input_top_margin)).empty())
552                         fl_set_choice(paper_->choice_top_margin_units,
553                                       default_unit);
554                 if (rtrim(fl_get_input(paper_->input_bottom_margin)).empty())
555                         fl_set_choice(paper_->choice_bottom_margin_units,
556                                       default_unit);
557                 if (rtrim(fl_get_input(paper_->input_inner_margin)).empty())
558                         fl_set_choice(paper_->choice_inner_margin_units,
559                                       default_unit);
560                 if (rtrim(fl_get_input(paper_->input_outer_margin)).empty())
561                         fl_set_choice(paper_->choice_outer_margin_units,
562                                       default_unit);
563                 if (rtrim(fl_get_input(paper_->input_head_height)).empty())
564                         fl_set_choice(paper_->choice_head_height_units,
565                                       default_unit);
566                 if (rtrim(fl_get_input(paper_->input_head_sep)).empty())
567                         fl_set_choice(paper_->choice_head_sep_units,
568                                       default_unit);
569                 if (rtrim(fl_get_input(paper_->input_foot_skip)).empty())
570                         fl_set_choice(paper_->choice_foot_skip_units,
571                                       default_unit);
572         }
573
574         if (ob == paper_->choice_papersize ||
575             ob == paper_->radio_portrait ||
576             ob == paper_->radio_landscape) {
577
578                 setEnabled(paper_->choice_paperpackage,
579                            //either default papersize (preferences)
580                            //or document papersize has to be A4
581                            (fl_get_choice(paper_->choice_papersize) == 7
582                             || fl_get_choice(paper_->choice_papersize) == 1
583                             && lyxrc.default_papersize == 5)
584                            && fl_get_button(paper_->radio_portrait));
585         }
586
587         if (ob == paper_->choice_paperpackage) {
588                 if (fl_get_choice(paper_->choice_paperpackage) != 1) {
589                         fl_set_button(paper_->check_use_geometry, 0);
590
591                         setEnabled(paper_->input_top_margin,    false);
592                         setEnabled(paper_->input_bottom_margin, false);
593                         setEnabled(paper_->input_inner_margin,  false);
594                         setEnabled(paper_->input_outer_margin,  false);
595                         setEnabled(paper_->input_head_height,   false);
596                         setEnabled(paper_->input_head_sep,      false);
597                         setEnabled(paper_->input_foot_skip,     false);
598                         setEnabled(paper_->choice_top_margin_units,    false);
599                         setEnabled(paper_->choice_bottom_margin_units, false);
600                         setEnabled(paper_->choice_inner_margin_units,  false);
601                         setEnabled(paper_->choice_outer_margin_units,  false);
602                         setEnabled(paper_->choice_head_height_units,   false);
603                         setEnabled(paper_->choice_head_sep_units,      false);
604                         setEnabled(paper_->choice_foot_skip_units,     false);
605                 }
606         }
607
608         if (ob == paper_->check_use_geometry) {
609                 //don't allow switching geometry off in custom papersize mode
610                 //nor in A3, B3, and B4
611                 int const choice = fl_get_choice(paper_->choice_papersize);
612                 if (choice == 2 || choice == 6 || choice == 9 || choice == 10)
613                         fl_set_button(paper_->check_use_geometry, 1);
614
615                 fl_set_choice(paper_->choice_paperpackage,
616                               BufferParams::PACKAGE_NONE + 1);
617
618                 bool const use_geom = fl_get_button(paper_->check_use_geometry);
619                 setEnabled(paper_->input_top_margin,    use_geom);
620                 setEnabled(paper_->input_bottom_margin, use_geom);
621                 setEnabled(paper_->input_inner_margin,  use_geom);
622                 setEnabled(paper_->input_outer_margin,  use_geom);
623                 setEnabled(paper_->input_head_height,   use_geom);
624                 setEnabled(paper_->input_head_sep,      use_geom);
625                 setEnabled(paper_->input_foot_skip,     use_geom);
626                 setEnabled(paper_->choice_top_margin_units,    use_geom);
627                 setEnabled(paper_->choice_bottom_margin_units, use_geom);
628                 setEnabled(paper_->choice_inner_margin_units,  use_geom);
629                 setEnabled(paper_->choice_outer_margin_units,  use_geom);
630                 setEnabled(paper_->choice_head_height_units,   use_geom);
631                 setEnabled(paper_->choice_head_sep_units,      use_geom);
632                 setEnabled(paper_->choice_foot_skip_units,     use_geom);
633         }
634
635         return CheckDocumentInput(ob, 0);
636 }
637
638
639 void FormDocument::ComboInputCB(int, void * v, Combox * combox)
640 {
641         FormDocument * pre = static_cast<FormDocument*>(v);
642         if (combox == pre->combo_doc_class.get())
643                 pre->CheckChoiceClass(0, 0);
644         pre->bc().valid(pre->CheckDocumentInput(0,0));
645 }
646
647
648 bool FormDocument::class_apply(BufferParams &params)
649 {
650         bool redo = false;
651
652         // If default skip is a "Length" but there's no text in the
653         // input field, reset the kind to "Medskip", which is the default.
654         if ((fl_get_choice (class_->choice_doc_skip) == 4) &&
655             !*(fl_get_input (class_->input_doc_skip))) {
656                 fl_set_choice (class_->choice_doc_skip, 2);
657         }
658         params.fonts = fl_get_choice_text(class_->choice_doc_fonts);
659         params.fontsize = fl_get_choice_text(class_->choice_doc_fontsize);
660         params.pagestyle = fl_get_choice_text(class_->choice_doc_pagestyle);
661
662         params.textclass = combo_doc_class->get() - 1;
663
664         BufferParams::PARSEP tmpsep = params.paragraph_separation;
665         if (fl_get_button(class_->radio_doc_indent))
666                 params.paragraph_separation = BufferParams::PARSEP_INDENT;
667         else
668                 params.paragraph_separation = BufferParams::PARSEP_SKIP;
669         if (tmpsep != params.paragraph_separation)
670                 redo = true;
671
672         VSpace tmpdefskip = params.getDefSkip();
673         switch (fl_get_choice (class_->choice_doc_skip)) {
674         case 1:
675                 params.setDefSkip(VSpace(VSpace::SMALLSKIP));
676                 break;
677         case 2:
678                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
679                 break;
680         case 3:
681                 params.setDefSkip(VSpace(VSpace::BIGSKIP));
682                 break;
683         case 4:
684         {
685                 string const length =
686                         getLengthFromWidgets(class_->input_doc_skip,
687                                              class_->choice_default_skip_units);
688
689                 params.setDefSkip(VSpace(LyXGlueLength(length)));
690                 break;
691         }
692         default:
693                 // DocumentDefskipCB assures that this never happens
694                 params.setDefSkip(VSpace(VSpace::MEDSKIP));
695                 break;
696         }
697         if (!(tmpdefskip == params.getDefSkip()))
698                 redo = true;
699
700         if (fl_get_button(class_->radio_doc_columns_two))
701                 params.columns = 2;
702         else
703                 params.columns = 1;
704         if (fl_get_button(class_->radio_doc_sides_two))
705                 params.sides = LyXTextClass::TwoSides;
706         else
707                 params.sides = LyXTextClass::OneSide;
708
709         Spacing tmpSpacing = params.spacing;
710         switch (fl_get_choice(class_->choice_doc_spacing)) {
711         case 1:
712                 lyxerr[Debug::INFO] << "Spacing: SINGLE\n";
713                 params.spacing.set(Spacing::Single);
714                 break;
715         case 2:
716                 lyxerr[Debug::INFO] << "Spacing: ONEHALF\n";
717                 params.spacing.set(Spacing::Onehalf);
718                 break;
719         case 3:
720                 lyxerr[Debug::INFO] << "Spacing: DOUBLE\n";
721                 params.spacing.set(Spacing::Double);
722                 break;
723         case 4:
724                 lyxerr[Debug::INFO] << "Spacing: OTHER\n";
725                 params.spacing.set(Spacing::Other,
726                                    fl_get_input(class_->input_doc_spacing));
727                 break;
728         }
729         if (tmpSpacing != params.spacing)
730                 redo = true;
731
732         params.options = fl_get_input(class_->input_doc_extra);
733
734         return redo;
735 }
736
737
738 bool FormDocument::class_apply()
739 {
740         BufferParams &params = lv_.buffer()->params;
741
742         unsigned int const old_class = params.textclass;
743
744         bool redo = class_apply(params);
745
746         if (params.textclass != old_class) {
747                 // try to load new_class
748                 if (textclasslist[params.textclass].load()) {
749                         // successfully loaded
750                         redo = true;
751                         setMinibuffer(&lv_, _("Converting document to new document class..."));
752                         int ret = CutAndPaste::SwitchLayoutsBetweenClasses(
753                                 old_class, params.textclass,
754                                 &*(lv_.buffer()->paragraphs.begin()),
755                                 lv_.buffer()->params);
756                         if (ret) {
757                                 string s;
758                                 if (ret == 1) {
759                                         s = _("One paragraph couldn't be converted");
760                                 } else {
761                                         s += tostr(ret);
762                                         s += _(" paragraphs couldn't be converted");
763                                 }
764                                 Alert::alert(_("Conversion Errors!"),s,
765                                              _("into chosen document class"));
766                         }
767
768                 } else {
769                         // problem changing class -- warn user and retain old style
770                         Alert::alert(_("Conversion Errors!"),
771                                      _("Errors loading new document class."),
772                                      _("Reverting to original document class."));
773                         combo_doc_class->select(int(old_class) + 1);
774                 }
775         }
776
777         return redo;
778 }
779
780
781 void FormDocument::paper_apply(BufferParams & params)
782 {
783         params.papersize2 = char(fl_get_choice(paper_->choice_papersize) - 1);
784
785         params.paperpackage =
786                 char(fl_get_choice(paper_->choice_paperpackage) - 1);
787
788         // set params.papersize from params.papersize2 and params.paperpackage
789         params.setPaperStuff();
790
791         params.use_geometry = fl_get_button(paper_->check_use_geometry);
792
793         if (fl_get_button(paper_->radio_landscape))
794                 params.orientation = BufferParams::ORIENTATION_LANDSCAPE;
795         else
796                 params.orientation = BufferParams::ORIENTATION_PORTRAIT;
797
798         params.paperwidth =
799                 getLengthFromWidgets(paper_->input_custom_width,
800                                      paper_->choice_custom_width_units);
801
802         params.paperheight =
803                 getLengthFromWidgets(paper_->input_custom_height,
804                                      paper_->choice_custom_height_units);
805
806         params.leftmargin =
807                 getLengthFromWidgets(paper_->input_inner_margin,
808                                      paper_->choice_inner_margin_units);
809
810         params.topmargin =
811                 getLengthFromWidgets(paper_->input_top_margin,
812                                      paper_->choice_top_margin_units);
813
814         params.rightmargin =
815                 getLengthFromWidgets(paper_->input_outer_margin,
816                                      paper_->choice_outer_margin_units);
817
818         params.bottommargin =
819                 getLengthFromWidgets(paper_->input_bottom_margin,
820                                      paper_->choice_bottom_margin_units);
821
822         params.headheight =
823                 getLengthFromWidgets(paper_->input_head_height,
824                                      paper_->choice_head_height_units);
825
826         params.headsep =
827                 getLengthFromWidgets(paper_->input_head_sep,
828                                      paper_->choice_head_sep_units);
829
830         params.footskip =
831                 getLengthFromWidgets(paper_->input_foot_skip,
832                                      paper_->choice_foot_skip_units);
833 }
834
835
836 void FormDocument::paper_apply()
837 {
838         paper_apply(lv_.buffer()->params);
839 }
840
841
842 bool FormDocument::language_apply(BufferParams & params)
843 {
844         InsetQuotes::quote_language lga = InsetQuotes::EnglishQ;
845         bool redo = false;
846
847         switch (fl_get_choice(language_->choice_quotes_language) - 1) {
848         case 0:
849                 lga = InsetQuotes::EnglishQ;
850                 break;
851         case 1:
852                 lga = InsetQuotes::SwedishQ;
853                 break;
854         case 2:
855                 lga = InsetQuotes::GermanQ;
856                 break;
857         case 3:
858                 lga = InsetQuotes::PolishQ;
859                 break;
860         case 4:
861                 lga = InsetQuotes::FrenchQ;
862                 break;
863         case 5:
864                 lga = InsetQuotes::DanishQ;
865                 break;
866         }
867         params.quotes_language = lga;
868         if (fl_get_button(language_->radio_single))
869                 params.quotes_times = InsetQuotes::SingleQ;
870         else
871                 params.quotes_times = InsetQuotes::DoubleQ;
872
873         int const pos = combo_language->get();
874         Language const * old_language = params.language;
875         Language const * new_language = languages.getLanguage(lang_[pos-1]);
876         if (!new_language)
877                 new_language = default_language;
878
879         if (old_language != new_language
880             && old_language->RightToLeft() == new_language->RightToLeft()
881             && !lv_.buffer()->isMultiLingual())
882                 lv_.buffer()->changeLanguage(old_language, new_language);
883
884         if (old_language != new_language) {
885                 redo = true;
886         }
887
888         params.language = new_language;
889         params.inputenc = fl_get_choice_text(language_->choice_inputenc);
890
891         return redo;
892 }
893
894
895 bool FormDocument::language_apply()
896 {
897         return language_apply(lv_.buffer()->params);
898 }
899
900
901 bool FormDocument::options_apply(BufferParams & params)
902 {
903         bool redo = false;
904
905         params.graphicsDriver =
906                 fl_get_choice_text(options_->choice_postscript_driver);
907         params.use_amsmath = fl_get_button(options_->check_use_amsmath);
908         params.use_natbib  = fl_get_button(options_->check_use_natbib);
909         params.use_numerical_citations  =
910                 fl_get_choice(options_->choice_citation_format) - 1;
911
912         int tmpchar = int(fl_get_counter_value(options_->counter_secnumdepth));
913         if (params.secnumdepth != tmpchar)
914                 redo = true;
915         params.secnumdepth = tmpchar;
916
917         params.tocdepth = int(fl_get_counter_value(options_->counter_tocdepth));
918
919         params.float_placement =
920                 fl_get_input(options_->input_float_placement);
921
922         return redo;
923 }
924
925
926 bool FormDocument::options_apply()
927 {
928         return options_apply(lv_.buffer()->params);
929 }
930
931
932 void FormDocument::bullets_apply(BufferParams & params)
933 {
934         /* update the bullet settings */
935         BufferParams & buf_params = lv_.buffer()->params;
936
937         // a little bit of loop unrolling
938         params.user_defined_bullets[0] = buf_params.temp_bullets[0];
939         params.user_defined_bullets[1] = buf_params.temp_bullets[1];
940         params.user_defined_bullets[2] = buf_params.temp_bullets[2];
941         params.user_defined_bullets[3] = buf_params.temp_bullets[3];
942 }
943
944
945 void FormDocument::bullets_apply()
946 {
947         bullets_apply(lv_.buffer()->params);
948 }
949
950 void FormDocument::UpdateClassParams(BufferParams const & params)
951 {
952         // These are the params that have to be updated on any class change
953         // (even if the class defaults are not used) (JSpitzm 2002-04-08)
954
955         LyXTextClass const & tclass = textclasslist[params.textclass];
956
957         combo_doc_class->select(tclass.description());
958         fl_clear_choice(class_->choice_doc_fontsize);
959         fl_addto_choice(class_->choice_doc_fontsize, "default");
960         fl_addto_choice(class_->choice_doc_fontsize,
961                         tclass.opt_fontsize().c_str());
962         fl_set_choice_text(class_->choice_doc_fontsize,
963                         params.fontsize.c_str());
964         fl_clear_choice(class_->choice_doc_pagestyle);
965         fl_addto_choice(class_->choice_doc_pagestyle, "default");
966         fl_addto_choice(class_->choice_doc_pagestyle,
967                         tclass.opt_pagestyle().c_str());
968         fl_set_choice_text(class_->choice_doc_pagestyle,
969                         params.pagestyle.c_str());
970
971 }
972
973 void FormDocument::class_update(BufferParams const & params)
974 {
975         if (!class_.get())
976                 return;
977
978         UpdateClassParams(params);
979
980         fl_set_choice_text(class_->choice_doc_fonts,
981                 params.fonts.c_str());
982         fl_set_button(class_->radio_doc_indent, 0);
983         fl_set_button(class_->radio_doc_skip, 0);
984         if (params.paragraph_separation == BufferParams::PARSEP_INDENT)
985                 fl_set_button(class_->radio_doc_indent, 1);
986         else
987                 fl_set_button(class_->radio_doc_skip, 1);
988
989         bool const input_length = fl_get_choice(class_->choice_doc_skip) == 4;
990         setEnabled(class_->choice_default_skip_units, input_length);
991         setEnabled(class_->input_doc_skip, input_length);
992
993         switch (params.getDefSkip().kind()) {
994         case VSpace::SMALLSKIP:
995                 fl_set_choice (class_->choice_doc_skip, 1);
996                 break;
997         case VSpace::MEDSKIP:
998                 fl_set_choice (class_->choice_doc_skip, 2);
999                 break;
1000         case VSpace::BIGSKIP:
1001                 fl_set_choice (class_->choice_doc_skip, 3);
1002                 break;
1003         case VSpace::LENGTH:
1004         {
1005                 int const paperchoice = fl_get_choice(paper_->choice_papersize);
1006                 bool const metric = (paperchoice == 1 && lyxrc.default_papersize > 3)
1007                         || paperchoice == 2 || paperchoice > 5;
1008                 string const default_unit = metric ? "cm" : "in";
1009                 string const length = params.getDefSkip().asLyXCommand();
1010                 updateWidgetsFromLengthString(class_->input_doc_skip,
1011                                               class_->choice_default_skip_units,
1012                                               length, default_unit);
1013                 break;
1014         }
1015         default:
1016                 fl_set_choice (class_->choice_doc_skip, 2);
1017                 break;
1018         }
1019         fl_set_button(class_->radio_doc_sides_one, 0);
1020         fl_set_button(class_->radio_doc_sides_two, 0);
1021         setEnabled(class_->choice_doc_skip,
1022                    fl_get_button(class_->radio_doc_skip));
1023
1024         if (params.sides == LyXTextClass::TwoSides)
1025                 fl_set_button(class_->radio_doc_sides_two, 1);
1026         else
1027                 fl_set_button(class_->radio_doc_sides_one, 1);
1028         fl_set_button(class_->radio_doc_columns_one, 0);
1029         fl_set_button(class_->radio_doc_columns_two, 0);
1030         if (params.columns == 2)
1031                 fl_set_button(class_->radio_doc_columns_two, 1);
1032         else
1033                 fl_set_button(class_->radio_doc_columns_one, 1);
1034
1035         fl_set_input(class_->input_doc_spacing, "");
1036         setEnabled(class_->input_doc_spacing, false);
1037
1038         switch (params.spacing.getSpace()) {
1039         case Spacing::Default: // nothing bad should happen with this
1040         case Spacing::Single:
1041                 // \singlespacing
1042                 fl_set_choice(class_->choice_doc_spacing, 1);
1043                 break;
1044         case Spacing::Onehalf:
1045                 // \onehalfspacing
1046                 fl_set_choice(class_->choice_doc_spacing, 2);
1047                 break;
1048         case Spacing::Double:
1049                 // \doublespacing
1050                 fl_set_choice(class_->choice_doc_spacing, 3);
1051                 break;
1052         case Spacing::Other:
1053         {
1054                 fl_set_choice(class_->choice_doc_spacing, 4);
1055                 char sval[20];
1056                 sprintf(sval,"%g",params.spacing.getValue());
1057                 fl_set_input(class_->input_doc_spacing, sval);
1058                 setEnabled(class_->input_doc_spacing, true);
1059                 break;
1060         }
1061         }
1062         if (!params.options.empty())
1063                 fl_set_input(class_->input_doc_extra, params.options.c_str());
1064         else
1065                 fl_set_input(class_->input_doc_extra, "");
1066 }
1067
1068
1069 void FormDocument::language_update(BufferParams const & params)
1070 {
1071         if (!language_.get())
1072                 return;
1073
1074         int const pos = int(findPos(lang_, params.language->lang()));
1075         combo_language->select(pos+1);
1076
1077         fl_set_choice_text(language_->choice_inputenc, params.inputenc.c_str());
1078         fl_set_choice(language_->choice_quotes_language, params.quotes_language + 1);
1079         fl_set_button(language_->radio_single, 0);
1080         fl_set_button(language_->radio_double, 0);
1081         if (params.quotes_times == InsetQuotes::SingleQ)
1082                 fl_set_button(language_->radio_single, 1);
1083         else
1084                 fl_set_button(language_->radio_double, 1);
1085 }
1086
1087
1088 void FormDocument::options_update(BufferParams const & params)
1089 {
1090         if (!options_.get())
1091                 return;
1092
1093         fl_set_choice_text(options_->choice_postscript_driver,
1094                            params.graphicsDriver.c_str());
1095         fl_set_button(options_->check_use_amsmath, params.use_amsmath);
1096         fl_set_button(options_->check_use_natbib,  params.use_natbib);
1097         fl_set_choice(options_->choice_citation_format,
1098                       int(params.use_numerical_citations)+1);
1099         setEnabled(options_->choice_citation_format, params.use_natbib);
1100         fl_set_counter_value(options_->counter_secnumdepth, params.secnumdepth);
1101         fl_set_counter_value(options_->counter_tocdepth, params.tocdepth);
1102         if (!params.float_placement.empty())
1103                 fl_set_input(options_->input_float_placement,
1104                              params.float_placement.c_str());
1105         else
1106                 fl_set_input(options_->input_float_placement, "");
1107 }
1108
1109
1110 void FormDocument::paper_update(BufferParams const & params)
1111 {
1112         if (!paper_.get())
1113                 return;
1114
1115         fl_set_choice(paper_->choice_papersize, params.papersize2 + 1);
1116         fl_set_choice(paper_->choice_paperpackage, params.paperpackage + 1);
1117         fl_set_button(paper_->check_use_geometry, params.use_geometry);
1118
1119         int const paperchoice = fl_get_choice(paper_->choice_papersize);
1120         bool const useCustom = paperchoice == 2;
1121         bool const useGeom = fl_get_button(paper_->check_use_geometry);
1122
1123         fl_set_button(paper_->radio_portrait, 0);
1124         setEnabled(paper_->radio_portrait, !useCustom);
1125         fl_set_button(paper_->radio_landscape, 0);
1126         setEnabled(paper_->radio_landscape, !useCustom);
1127
1128         if (params.orientation == BufferParams::ORIENTATION_LANDSCAPE)
1129                 fl_set_button(paper_->radio_landscape, 1);
1130         else
1131                 fl_set_button(paper_->radio_portrait, 1);
1132         setEnabled(paper_->choice_paperpackage,
1133                    //either default papersize (preferences)
1134                    //or document papersize has to be A4
1135                    (paperchoice == 7
1136                     || paperchoice == 1 && lyxrc.default_papersize == 5)
1137                    && fl_get_button(paper_->radio_portrait));
1138
1139         // Default unit choice is cm if metric, inches if US paper.
1140         bool const metric = (paperchoice == 1 && lyxrc.default_papersize > 3)
1141                 || paperchoice == 2 || paperchoice > 5;
1142         string const default_unit = metric ? "cm" : "in";
1143         updateWidgetsFromLengthString(paper_->input_custom_width,
1144                                       paper_->choice_custom_width_units,
1145                                       params.paperwidth, default_unit);
1146         setEnabled(paper_->input_custom_width, useCustom);
1147         setEnabled(paper_->choice_custom_width_units, useCustom);
1148
1149         updateWidgetsFromLengthString(paper_->input_custom_height,
1150                                       paper_->choice_custom_height_units,
1151                                       params.paperheight, default_unit);
1152         setEnabled(paper_->input_custom_height, useCustom);
1153         setEnabled(paper_->choice_custom_height_units, useCustom);
1154
1155         updateWidgetsFromLengthString(paper_->input_inner_margin,
1156                                       paper_->choice_inner_margin_units,
1157                                       params.leftmargin, default_unit);
1158         setEnabled(paper_->input_inner_margin, useGeom);
1159         setEnabled(paper_->choice_inner_margin_units, useGeom);
1160
1161         updateWidgetsFromLengthString(paper_->input_top_margin,
1162                                       paper_->choice_top_margin_units,
1163                                       params.topmargin, default_unit);
1164         setEnabled(paper_->input_top_margin, useGeom);
1165         setEnabled(paper_->choice_top_margin_units, useGeom);
1166
1167         updateWidgetsFromLengthString(paper_->input_outer_margin,
1168                                       paper_->choice_outer_margin_units,
1169                                       params.rightmargin, default_unit);
1170         setEnabled(paper_->input_outer_margin, useGeom);
1171         setEnabled(paper_->choice_outer_margin_units, useGeom);
1172
1173         updateWidgetsFromLengthString(paper_->input_bottom_margin,
1174                                       paper_->choice_bottom_margin_units,
1175                                       params.bottommargin, default_unit);
1176         setEnabled(paper_->input_bottom_margin, useGeom);
1177         setEnabled(paper_->choice_bottom_margin_units, useGeom);
1178
1179         updateWidgetsFromLengthString(paper_->input_head_height,
1180                                       paper_->choice_head_height_units,
1181                                       params.headheight, default_unit);
1182         setEnabled(paper_->input_head_height, useGeom);
1183         setEnabled(paper_->choice_head_height_units, useGeom);
1184
1185         updateWidgetsFromLengthString(paper_->input_head_sep,
1186                                       paper_->choice_head_sep_units,
1187                                       params.headsep, default_unit);
1188         setEnabled(paper_->input_head_sep, useGeom);
1189         setEnabled(paper_->choice_head_sep_units, useGeom);
1190
1191         updateWidgetsFromLengthString(paper_->input_foot_skip,
1192                                       paper_->choice_foot_skip_units,
1193                                       params.footskip, default_unit);
1194         setEnabled(paper_->input_foot_skip, useGeom);
1195         setEnabled(paper_->choice_foot_skip_units, useGeom);
1196
1197         fl_set_focus_object(paper_->form, paper_->choice_papersize);
1198 }
1199
1200
1201 void FormDocument::bullets_update(BufferParams const & params)
1202 {
1203         if (!bullets_.get() ||
1204             ((XpmVersion<4) ||
1205              (XpmVersion==4 && XpmRevision<7)))
1206                 return;
1207
1208         bool const isLinuxDoc = lv_.buffer()->isLinuxDoc();
1209         setEnabled(fbullet, !isLinuxDoc);
1210
1211         if (isLinuxDoc) return;
1212
1213         fl_set_button(bullets_->radio_bullet_depth_1, 1);
1214         fl_set_input(bullets_->input_bullet_latex,
1215                      params.user_defined_bullets[0].getText().c_str());
1216         fl_set_choice(bullets_->choice_bullet_size,
1217                       params.user_defined_bullets[0].getSize() + 2);
1218 }
1219
1220
1221 void FormDocument::checkReadOnly()
1222 {
1223         if (bc().readOnly(lv_.buffer()->isReadonly())) {
1224                 combo_doc_class->deactivate();
1225                 combo_language->deactivate();
1226                 postWarning(_("Document is read-only."
1227                               " No changes to layout permitted."));
1228         } else {
1229                 combo_doc_class->activate();
1230                 combo_language->activate();
1231                 clearMessage();
1232         }
1233 }
1234
1235
1236 bool FormDocument::CheckDocumentInput(FL_OBJECT * ob, long)
1237 {
1238         string str;
1239         bool ok = true;
1240         char const * input;
1241
1242         // this has to be all out of if/elseif because it has to deactivate
1243         // the document buttons and so the whole stuff has to be tested again.
1244         // disable OK/Apply if input is not valid
1245         str = fl_get_input(class_->input_doc_skip);
1246         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1247         str = fl_get_input(paper_->input_custom_width);
1248         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1249         str = fl_get_input(paper_->input_custom_height);
1250         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1251         str = fl_get_input(paper_->input_outer_margin);
1252         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1253         str = fl_get_input(paper_->input_inner_margin);
1254         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1255         str = fl_get_input(paper_->input_top_margin);
1256         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1257         str = fl_get_input(paper_->input_bottom_margin);
1258         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1259         str = fl_get_input(paper_->input_head_height);
1260         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1261         str = fl_get_input(paper_->input_head_sep);
1262         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1263         str = fl_get_input(paper_->input_foot_skip);
1264         ok = ok && (str.empty() || isValidLength(str) || isStrDbl(str));
1265
1266         //display warning if input is not valid
1267         if (ob == class_->input_doc_skip
1268             || ob == paper_->input_custom_width
1269             || ob == paper_->input_custom_height
1270             || ob == paper_->input_outer_margin
1271             || ob == paper_->input_inner_margin
1272             || ob == paper_->input_top_margin
1273             || ob == paper_->input_bottom_margin
1274             || ob == paper_->input_head_height
1275             || ob == paper_->input_head_sep
1276             || ob == paper_->input_foot_skip) {
1277                 if (!ok) {
1278                         postWarning(_("Invalid Length (valid example: 10mm)"));
1279                         return false;
1280                 } else {
1281                         clearMessage();
1282                         return true;
1283                 }
1284         }
1285
1286         // "Synchronize" the choice and the input field, so that it
1287         // is impossible to commit senseless data.
1288         input = fl_get_input (class_->input_doc_skip);
1289         if ((fl_get_choice(class_->choice_doc_skip) == 4) && !*input)
1290                 ok = false;
1291         else if (fl_get_choice(class_->choice_doc_skip) != 4)
1292                 fl_set_input (class_->input_doc_skip, "");
1293
1294         input = fl_get_input(class_->input_doc_spacing);
1295         if ((fl_get_choice(class_->choice_doc_spacing) == 4) && !*input)
1296                 ok = false;
1297         else if (fl_get_choice(class_->choice_doc_spacing) != 4)
1298                 fl_set_input (class_->input_doc_spacing, "");
1299         return ok;
1300 }
1301
1302
1303 void FormDocument::ChoiceBulletSize(FL_OBJECT * ob, long /*data*/)
1304 {
1305         BufferParams & param = lv_.buffer()->params;
1306
1307         // convert from 1-6 range to -1-4
1308         param.temp_bullets[current_bullet_depth].setSize(fl_get_choice(ob) - 2);
1309         fl_set_input(bullets_->input_bullet_latex,
1310                      param.temp_bullets[current_bullet_depth].getText().c_str());
1311 }
1312
1313
1314 void FormDocument::InputBulletLaTeX(FL_OBJECT *, long)
1315 {
1316         BufferParams & param = lv_.buffer()->params;
1317
1318         param.temp_bullets[current_bullet_depth].
1319                 setText(fl_get_input(bullets_->input_bullet_latex));
1320 }
1321
1322
1323 void FormDocument::BulletDepth(FL_OBJECT * ob)
1324 {
1325         /* Should I do the following:                                 */
1326         /*  1. change to the panel that the current bullet belongs in */
1327         /*  2. show that bullet as selected                           */
1328         /*  3. change the size setting to the size of the bullet in Q.*/
1329         /*  4. display the latex equivalent in the latex box          */
1330         /*                                                            */
1331         /* I'm inclined to just go with 3 and 4 at the moment and     */
1332         /* maybe try to support the others later                      */
1333         BufferParams & param = lv_.buffer()->params;
1334
1335         int data = 0;
1336         if (ob == bullets_->radio_bullet_depth_1)
1337                 data = 0;
1338         else if (ob == bullets_->radio_bullet_depth_2)
1339                 data = 1;
1340         else if (ob == bullets_->radio_bullet_depth_3)
1341                 data = 2;
1342         else if (ob == bullets_->radio_bullet_depth_4)
1343                 data = 3;
1344
1345         switch (fl_get_button_numb(ob)) {
1346         case 3:
1347                 // right mouse button resets to default
1348                 param.temp_bullets[data] = ITEMIZE_DEFAULTS[data];
1349         default:
1350                 current_bullet_depth = data;
1351                 fl_set_input(bullets_->input_bullet_latex,
1352                              param.temp_bullets[data].getText().c_str());
1353                 fl_set_choice(bullets_->choice_bullet_size,
1354                               param.temp_bullets[data].getSize() + 2);
1355         }
1356 }
1357
1358
1359 void FormDocument::BulletPanel(FL_OBJECT * ob)
1360 {
1361         /* Here we have to change the background pixmap to that selected */
1362         /* by the user. (eg. standard.xpm, psnfss1.xpm etc...)           */
1363
1364         int data = 0;
1365         if (ob == bullets_->radio_bullet_panel_standard)
1366                 data = 0;
1367         else if (ob == bullets_->radio_bullet_panel_maths)
1368                 data = 1;
1369         else if (ob == bullets_->radio_bullet_panel_ding2)
1370                 data = 2;
1371         else if (ob == bullets_->radio_bullet_panel_ding3)
1372                 data = 3;
1373         else if (ob == bullets_->radio_bullet_panel_ding4)
1374                 data = 4;
1375         else if (ob == bullets_->radio_bullet_panel_ding1)
1376                 data = 5;
1377
1378         if (data != current_bullet_panel) {
1379                 fl_freeze_form(bullets_->form);
1380                 current_bullet_panel = data;
1381
1382                 /* free the current pixmap */
1383                 fl_free_bmtable_pixmap(bullets_->bmtable_bullet_panel);
1384                 string new_panel;
1385                 if (ob == bullets_->radio_bullet_panel_standard) {
1386                         new_panel = "standard";
1387                 } else if (ob == bullets_->radio_bullet_panel_maths ) {
1388                         new_panel = "amssymb";
1389                 } else if (ob == bullets_->radio_bullet_panel_ding2) {
1390                         new_panel = "psnfss1";
1391                 } else if (ob == bullets_->radio_bullet_panel_ding3) {
1392                         new_panel = "psnfss2";
1393                 } else if (ob == bullets_->radio_bullet_panel_ding4) {
1394                         new_panel = "psnfss3";
1395                 } else if (ob == bullets_->radio_bullet_panel_ding1) {
1396                         new_panel = "psnfss4";
1397                 } else {
1398                         /* something very wrong happened */
1399                         // play it safe for now but should be an exception
1400                         current_bullet_panel = 0;  // standard panel
1401                         new_panel = "standard";
1402                 }
1403                 new_panel += ".xpm";
1404                 fl_set_bmtable_pixmap_file(bullets_->bmtable_bullet_panel, 6, 6,
1405                                            LibFileSearch("images", new_panel).c_str());
1406                 fl_redraw_object(bullets_->bmtable_bullet_panel);
1407                 fl_unfreeze_form(bullets_->form);
1408         }
1409 }
1410
1411
1412 void FormDocument::BulletBMTable(FL_OBJECT * ob, long /*data*/)
1413 {
1414         /* handle the user input by setting the current bullet depth's pixmap */
1415         /* to that extracted from the current chosen position of the BMTable  */
1416         /* Don't forget to free the button's old pixmap first.                */
1417
1418         BufferParams & param = lv_.buffer()->params;
1419         int bmtable_button = fl_get_bmtable(ob);
1420
1421         /* try to keep the button held down till another is pushed */
1422         /*  fl_set_bmtable(ob, 1, bmtable_button); */
1423         param.temp_bullets[current_bullet_depth].setFont(current_bullet_panel);
1424         param.temp_bullets[current_bullet_depth].setCharacter(bmtable_button);
1425         fl_set_input(bullets_->input_bullet_latex,
1426                      param.temp_bullets[current_bullet_depth].getText().c_str());
1427 }
1428
1429
1430 void FormDocument::CheckChoiceClass(FL_OBJECT * ob, long)
1431 {
1432         if (!ob)
1433                 ob = class_->choice_doc_class;
1434
1435         lv_.prohibitInput();
1436
1437         unsigned int tc = combo_doc_class->get() - 1;
1438         if (textclasslist[tc].load()) {
1439                 // we use a copy of the bufferparams because we do not
1440                 // want to modify them yet.
1441                 BufferParams params = lv_.buffer()->params;
1442
1443                 if (lyxrc.auto_reset_options) {
1444                         params.textclass = tc;
1445                         params.useClassDefaults();
1446                         UpdateLayoutDocument(params);
1447                 } else {
1448                         // update the params which are needed in any case
1449                         // (fontsizes, pagestyle)
1450                         params.textclass = tc;
1451                         UpdateClassParams(params);
1452                 }
1453
1454         } else {
1455                 // unable to load new style
1456                 Alert::alert(_("Conversion Errors!"),
1457                              _("Unable to switch to new document class."),
1458                              _("Reverting to original document class."));
1459                 combo_doc_class->select(int(lv_.buffer()->params.textclass) + 1);
1460         }
1461         lv_.allowInput();
1462 }
1463
1464
1465 void FormDocument::UpdateLayoutDocument(BufferParams const & params)
1466 {
1467         if (!dialog_.get())
1468                 return;
1469
1470         checkReadOnly();
1471         class_update(params);
1472         paper_update(params);
1473         language_update(params);
1474         options_update(params);
1475         bullets_update(params);
1476 }