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