home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / lyx-0.13.2.tar.gz / lyx-0.13.2.tar / lyx-0.13.2 / src / buffer.C < prev    next >
C/C++ Source or Header  |  1998-04-23  |  87KB  |  3,331 lines

  1. /* This file is part of
  2.  * ======================================================
  3.  * 
  4.  *           LyX, The Document Processor
  5.  *
  6.  *         Copyright (C) 1995 Matthias Ettrich
  7.  *           Copyright (C) 1995-1998 The LyX Team.
  8.  *
  9.  *           This file is Copyright (C) 1996-1998
  10.  *           Lars Gullik Bj°nnes
  11.  *
  12.  *======================================================
  13.  */
  14. #include <config.h>
  15.  
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18.  
  19. #if defined(sgi) && !defined(__GNUC__)
  20. #include <bstring.h>
  21. #endif
  22.  
  23. #ifdef __GNUG__
  24. #pragma implementation
  25. #endif
  26.  
  27. #include "definitions.h"
  28. #include "buffer.h"
  29. #include "bufferlist.h"
  30. #include "lyx_main.h"
  31. #include "lyx_gui_misc.h"
  32. #include "lyxrc.h"
  33. #include "lyxlex.h"
  34. #include "tex-strings.h"
  35. #include "linuxdoc.h"
  36. #include "layout.h"
  37. #include "lyx_cb.h"
  38. #include "minibuffer.h"
  39. #include "lyxfont.h"
  40. #include "formulamacro.h"
  41. #include "lyxinset.h"
  42. #include "inseterror.h"
  43. #include "insetlabel.h"
  44. #include "insetref.h"
  45. #include "insetinfo.h"
  46. #include "insetquotes.h"
  47. #include "insetlatexaccent.h"
  48. #include "insetbib.h" 
  49. #include "insetindex.h" 
  50. #include "insetinclude.h"
  51. #include "insettoc.h"
  52. #include "insetlof.h"
  53. #include "insetlot.h"
  54. #include "insetloa.h"
  55. #include "insetparent.h"
  56. #include "insetspecialchar.h"
  57. #include "insetfig.h"
  58. #include "filetools.h"
  59. #include "path.h"
  60. #include "LaTeX.h"
  61. #include "Chktex.h"
  62. #include "LyXView.h"
  63. #include "error.h"
  64. #include "LaTeXFeatures.h"
  65. #include "syscall.h"
  66. #include "lyxlib.h"
  67. #include "FileInfo.h"
  68. #include "lyxtext.h"
  69. #include "gettext.h"
  70.  
  71.  
  72. //     $Id: buffer.C,v 1.1.1.1 1998/04/23 16:02:48 larsbj Exp $    
  73.  
  74. #if !defined(lint) && !defined(WITH_WARNINGS)
  75. static char vcid[] = "$Id: buffer.C,v 1.1.1.1 1998/04/23 16:02:48 larsbj Exp $";
  76. #endif /* lint */
  77.  
  78.  
  79. // Uncomment this line to enable a workaround for the weird behaviour
  80. // of the cursor between a displayed inset and last character
  81. // at the upper line. (Alejandro 20.9.96)
  82. // #define BREAK_BEFORE_INSET
  83.  
  84. /* Lars, when changing this file sometime in the future to a list,
  85.  * please check out the figinsets-sideeffects described at the
  86.  * beginning of figinset.C    Matthias (04.07.1996)
  87.  */
  88.  
  89.  
  90. // all these externs should eventually be removed.
  91. extern BufferList bufferlist;
  92. extern void SmallUpdate(signed char);
  93. extern unsigned char GetCurrentTextClass();
  94. extern void BeforeChange();
  95.  
  96. static const float LYX_FORMAT = 2.15;
  97.  
  98. extern int tex_code_break_column;
  99.  
  100. extern void FreeUpdateTimer();
  101.  
  102.  
  103. Buffer::Buffer(LString const & file, LyXRC *lyxrc, bool ronly)
  104. {
  105.     filename = file;
  106.     filepath = OnlyPath(file);
  107.     paragraph = NULL;
  108.     text = NULL;
  109.     the_locking_inset = NULL;
  110.     lyx_clean = true;
  111.     bak_clean = true;
  112.     dvi_clean = false;
  113.     dep_clean = NULL;
  114.     read_only = ronly;
  115.     inset_slept = false;
  116.     users = 0;
  117.     lyxvc.setBuffer(this);
  118.     lyxerr.debug("Buffer::Buffer()");
  119.     if (read_only || (lyxrc && lyxrc->use_tempdir)) {
  120.         tmppath = CreateBufferTmpDir();
  121.     } else tmppath.erase();
  122. }
  123.  
  124.  
  125. Buffer::~Buffer()
  126. {
  127.     lyxerr.debug("Buffer::~Buffer()");
  128.     // here the buffer should take care that it is
  129.     // saved properly, before it goes into the void.
  130.  
  131.     // make sure that views using this buffer
  132.     // forgets it.
  133.     if (users)
  134.         users->setBuffer(0);
  135.     
  136.     if (!tmppath.empty()) {
  137.         DestroyBufferTmpDir(tmppath);
  138.     }
  139.     
  140.     LyXParagraph *par = paragraph;
  141.     LyXParagraph *tmppar;
  142.     while (par) {
  143.         tmppar = par->next;
  144.         delete par;
  145.         par = tmppar;
  146.     }
  147.     paragraph = NULL;
  148.     delete text;
  149. }
  150.  
  151.  
  152. bool Buffer::saveParamsAsDefaults()
  153. {
  154.     LString fname = AddName(AddPath(user_lyxdir, "templates/"),
  155.                 "defaults.lyx");
  156.     Buffer defaults = Buffer(fname);
  157.     
  158.     // Use the current buffer's parameters as default
  159.     defaults.params.Copy(params);
  160.     // add an empty paragraph. Is this enough?
  161.     defaults.paragraph = new LyXParagraph();
  162.  
  163.     return defaults.writeFile(defaults.filename,false);
  164. }
  165.  
  166.  
  167. /// Update window titles of all users
  168. // Should work on a list
  169. void Buffer::updateTitles()
  170. {
  171.     if (users) users->getOwner()->updateWindowTitle();
  172. }
  173.  
  174.  
  175. /// Reset autosave timer of all users
  176. // Should work on a list
  177. void Buffer::resetAutosaveTimers()
  178. {
  179.     if (users) users->getOwner()->resetAutosaveTimer();
  180. }
  181.  
  182.  
  183. void Buffer::setFileName(LString const & newfile)
  184. {
  185.     filename = MakeAbsPath(newfile);
  186.     filepath = OnlyPath(filename);
  187.     setReadonly(IsFileWriteable(filename) == 0);
  188.     updateTitles();
  189. }
  190.  
  191. void Buffer::InsetUnlock()
  192. {
  193.     if (the_locking_inset) {
  194.         if (!inset_slept) the_locking_inset->InsetUnlock();
  195.         the_locking_inset = NULL;
  196.         text->FinishUndo();
  197.         inset_slept = false;
  198.     }
  199. }
  200.  
  201.  
  202. // Inserts a file into current document
  203. bool Buffer::insertLyXFile(LString const & filen)
  204.     //
  205.     // (c) CHT Software Service GmbH
  206.     // Uwe C. Schroeder
  207.     //
  208.     // Insert a Lyxformat - file into current buffer
  209.     //
  210.     // Moved from lyx_cb.C (Lgb)
  211. {
  212.     if (filen.empty()) return false;
  213.  
  214.     LString filename = MakeAbsPath(filen);
  215.  
  216.     // check if file exist
  217.     FileInfo fi(filename);
  218.  
  219.     if (!fi.exist() || !fi.readable()) {
  220.         WriteAlert(_("Error!"),
  221.                _("Cannot open specified file:"),
  222.                MakeDisplayPath(filename,50));
  223.         return false;
  224.     }
  225.     
  226.     BeforeChange();
  227.  
  228.     FilePtr myfile(filename, FilePtr::read);
  229.     if (!myfile()) {
  230.         WriteAlert(_("Error!"),
  231.                _("Cannot open specified file:"),
  232.                MakeDisplayPath(filename,50));
  233.         return false;
  234.     }
  235.     LyXLex lex(NULL, 0);
  236.     lex.setFile(myfile);
  237.     int c = fgetc(myfile());
  238.     ungetc(c, myfile);
  239.  
  240.     bool res = true;
  241.  
  242.     if (c=='#') {
  243.         lyxerr.debug("Will insert file with header");
  244.         res = readFile(lex, text->cursor.par);
  245.     } else {
  246.         lyxerr.debug("Will insert file without header");
  247.         res = readLyXformat2(lex, text->cursor.par);
  248.     }
  249.     resize();
  250.     return res;
  251. }
  252.  
  253.  
  254. //
  255. // Uwe C. Schroeder
  256. // changed to be public and have one parameter
  257. // if par = NULL normal behavior
  258. // else insert behavior
  259. // Returns false if "\the_end" is not read for formats >= 2.13. (Asger)
  260. bool Buffer::readLyXformat2(LyXLex &lex, LyXParagraph *par)
  261. {
  262.     LString tmptok;
  263.     Inset *inset;
  264.     int pos = 0;
  265.     int tmpret, tmpret2;
  266.     char depth = 0; // signed or unsigned?
  267.     LyXParagraph::footnote_flag footnoteflag = LyXParagraph::NO_FOOTNOTE;
  268.     LyXParagraph::footnote_kind footnotekind = LyXParagraph::FOOTNOTE;
  269.     bool the_end_read = false;
  270.  
  271.     LyXParagraph *return_par = NULL;
  272.     LyXFont font = LyXFont(LyXFont::ALL_INHERIT);
  273.  
  274.     // If we are inserting, we cheat and get a token in advance
  275.     bool has_token = false;
  276.     LString pretoken;
  277.  
  278.     if(!par) {
  279.         par = new LyXParagraph();
  280.     } else {
  281.         text->BreakParagraph();
  282.         return_par = text->FirstParagraph();
  283.         pos=0;
  284.         markDirty();
  285.         // We don't want to adopt the parameters from the
  286.         // document we insert, so we skip until the text begins:
  287.         while (lex.IsOK()) {
  288.             lex.nextToken();
  289.             pretoken = lex.GetString();
  290.             if (pretoken == "\\layout") {
  291.                 has_token = true;
  292.                 break;
  293.             }
  294.         }
  295.     }
  296.  
  297.     while (lex.IsOK()) {
  298.         if (has_token) {
  299.             has_token = false;
  300.         } else {
  301.             lex.nextToken();
  302.             pretoken = lex.GetString();
  303.         }
  304.  
  305.         // Profiling show this should give a lot: (Asger)
  306.         LString const token = pretoken;
  307.  
  308.         if (token.empty())
  309.             continue;
  310.         else if (token[0] != '\\') {
  311.             int n = token.length();
  312.             for (int i=0; i < n; i++) {
  313.                 par->InsertChar(pos, token[i]);
  314.                 par->SetFont(pos, font);
  315.                 pos++;
  316.             }
  317.         } else if (token == "\\i") {
  318.             inset = new InsetLatexAccent;
  319.             inset->Read(lex);
  320.             par->InsertChar(pos, LYX_META_INSET); 
  321.             
  322.             par->InsertInset(pos, inset);
  323.             par->SetFont(pos, font);
  324.             pos++;
  325.         } else if (token == "\\layout") {
  326.             if (!return_par) 
  327.                 return_par = par;
  328.             else 
  329.                 par = new LyXParagraph(par);
  330.             pos = 0;
  331.             lex.EatLine();
  332.             par->layout =
  333.                 lyxstyle.NumberOfLayout(params.textclass,
  334.                             lex.GetString());
  335.             if (par->layout == -1) // layout not found
  336.                 // use default layout "Standard" (0)
  337.                 par->layout = 0;
  338.             // Test whether the layout is obsolete.
  339.             LyXLayout* layout = lyxstyle.Style(params.textclass,
  340.                                par->layout); 
  341.             if (!layout->obsoleted_by.empty())
  342.                 par->layout = 
  343.                     lyxstyle.NumberOfLayout(params.textclass, 
  344.                                 layout->obsoleted_by);
  345.             par->footnoteflag = footnoteflag;
  346.             par->footnotekind = footnotekind;
  347.             par->depth = depth;
  348.             font = LyXFont(LyXFont::ALL_INHERIT);
  349.         } else if (token == "\\end_float") {
  350.             if (!return_par) 
  351.                 return_par = par;
  352.             else 
  353.                 par = new LyXParagraph(par);
  354.             footnotekind = LyXParagraph::FOOTNOTE;
  355.             footnoteflag = LyXParagraph::NO_FOOTNOTE;
  356.             pos = 0;
  357.             lex.EatLine();
  358.             par->layout = LYX_DUMMY_LAYOUT;
  359.             font = LyXFont(LyXFont::ALL_INHERIT);
  360.         } else if (token == "\\begin_float") {
  361.             tmpret = lex.FindToken(string_footnotekinds);
  362.             if (tmpret == -1) tmpret++;
  363.             if (tmpret != LYX_LAYOUT_DEFAULT) 
  364.                 footnotekind = (LyXParagraph::footnote_kind)tmpret; // bad
  365.             if (footnotekind == LyXParagraph::FOOTNOTE
  366.                 || footnotekind == LyXParagraph::MARGIN)
  367.                 footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
  368.             else 
  369.                 footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
  370.         } else if (token == "\\begin_deeper") {
  371.             depth++;
  372.         } else if (token == "\\end_deeper") {
  373.             if (!depth) {
  374.                 lex.printError("\\end_deeper: "
  375.                            "depth is already null");
  376.             }
  377.             else
  378.                 depth--;
  379.         } else if (token == "\\begin_preamble") {
  380.             params.readPreamble(lex);
  381.         } else if (token == "\\textclass") {
  382.             lex.EatLine();
  383.             params.textclass = lyxstyle.NumberOfClass(lex.GetString());
  384.             if (params.textclass == -1) {
  385.                 lex.printError("Unknown textclass `$$Token'");
  386.                 params.textclass = 0;
  387.             }
  388.             if (!lyxstyle.Load(params.textclass)) {
  389.                 // if the textclass wasn't loaded properly
  390.                 // we need to either substitute another
  391.                 // or stop loading the file.
  392.                 // I can substitute but I don't see how I can
  393.                 // stop loading... ideas??  ARRae980418
  394.                 WriteAlert(_("Textclass Loading Error!"),
  395.                            LString(_("Can't load textclass ")) +
  396.                        lyxstyle.NameOfClass(params.textclass),
  397.                        _("-- substituting default"));
  398.                 params.textclass = 0;
  399.             }
  400.         } else if (token == "\\options") {
  401.             lex.EatLine();
  402.             params.options = lex.GetString();
  403.         } else if (token == "\\language") {
  404.             params.readLanguage(lex);        
  405.         } else if (token == "\\fontencoding") {
  406.             lex.EatLine();
  407.         } else if (token == "\\inputencoding") {
  408.             lex.EatLine();
  409.             params.inputenc = lex.GetString();
  410.         } else if (token == "\\graphics") {
  411.             params.readGraphicsDriver(lex);
  412.         } else if (token == "\\fontscheme") {
  413.             lex.EatLine();
  414.             params.fonts = lex.GetString();
  415.         } else if (token == "\\noindent") {
  416.             par->noindent = true;
  417.         } else if (token == "\\fill_top") {
  418.             par->added_space_top = VSpace::VFILL;
  419.         } else if (token == "\\fill_bottom") {
  420.             par->added_space_bottom = VSpace::VFILL;
  421.         } else if (token == "\\line_top") {
  422.             par->line_top = true;
  423.         } else if (token == "\\line_bottom") {
  424.             par->line_bottom = true;
  425.         } else if (token == "\\pagebreak_top") {
  426.             par->pagebreak_top = true;
  427.         } else if (token == "\\pagebreak_bottom") {
  428.             par->pagebreak_bottom = true;
  429.         } else if (token == "\\paragraph_separation") {
  430.             tmpret = lex.FindToken(string_paragraph_separation);
  431.             if (tmpret == -1) tmpret++;
  432.             if (tmpret != LYX_LAYOUT_DEFAULT) 
  433.                 params.paragraph_separation = tmpret;
  434.         } else if (token == "\\defskip") {
  435.             lex.nextToken();
  436.             params.defskip = VSpace(lex.GetString());
  437.         } else if (token == "\\no_isolatin1") {
  438.             lex.nextToken();
  439.         } else if (token == "\\no_babel") {
  440.             lex.nextToken();
  441.         } else if (token == "\\no_epsfig") {
  442.             lex.nextToken();
  443.         } else if (token == "\\epsfig") { // obsolete
  444.             // Indeed it is obsolete, but we HAVE to be backwards
  445.             // compatible until 0.14, because otherwise all figures
  446.             // in existing documents are irretrivably lost. (Asger)
  447.             params.readGraphicsDriver(lex);
  448.         } else if (token == "\\quotes_language") {
  449.             tmpret = lex.FindToken(string_quotes_language);
  450.             if (tmpret == -1) tmpret++;
  451.             if (tmpret != LYX_LAYOUT_DEFAULT) {
  452.                 InsetQuotes::quote_language tmpl =
  453.                     InsetQuotes::EnglishQ;
  454.                 switch(tmpret) {
  455.                 case 0:
  456.                     tmpl = InsetQuotes::EnglishQ;
  457.                     break;
  458.                 case 1:
  459.                     tmpl = InsetQuotes::SwedishQ;
  460.                     break;
  461.                 case 2:
  462.                     tmpl = InsetQuotes::GermanQ;
  463.                     break;
  464.                 case 3:
  465.                     tmpl = InsetQuotes::PolishQ;
  466.                     break;
  467.                 case 4:
  468.                     tmpl = InsetQuotes::FrenchQ;
  469.                     break;
  470.                 case 5:
  471.                     tmpl = InsetQuotes::DanishQ;
  472.                     break;    
  473.                 }
  474.                 params.quotes_language = tmpl;
  475.             }
  476.         } else if (token == "\\quotes_times") {
  477.             lex.nextToken();
  478.             switch(lex.GetInteger()) {
  479.             case 1: 
  480.                 params.quotes_times = InsetQuotes::SingleQ; 
  481.                 break;
  482.             case 2: 
  483.                 params.quotes_times = InsetQuotes::DoubleQ; 
  484.                 break;
  485.             }
  486.                 } else if (token == "\\papersize") {
  487.                         if (format > 2.13)
  488.                                 tmpret = lex.FindToken(string_papersize);
  489.                         else
  490.                                 tmpret = lex.FindToken(string_oldpapersize);
  491.             if (tmpret == -1)
  492.                                 tmpret++;
  493.                         else
  494.                                 params.papersize2 = tmpret;
  495.                 } else if (token == "\\paperpackage") {
  496.             tmpret = lex.FindToken(string_paperpackages);
  497.             if (tmpret == -1) {
  498.                                 tmpret++;
  499.                                 params.paperpackage = PACKAGE_NONE;
  500.                         } else
  501.                                 params.paperpackage = tmpret;
  502.         } else if (token == "\\use_geometry") {
  503.             lex.nextToken();
  504.             params.use_geometry = lex.GetInteger();
  505.         } else if (token == "\\use_amsmath") {
  506.             lex.nextToken();
  507.             params.use_amsmath = lex.GetInteger();
  508.         } else if (token == "\\paperorientation") {
  509.             tmpret = lex.FindToken(string_orientation);
  510.             if (tmpret == -1) tmpret++;
  511.             if (tmpret != LYX_LAYOUT_DEFAULT) 
  512.                 params.orientation = tmpret;
  513.         } else if (token == "\\paperwidth") {
  514.             lex.next();
  515.             params.paperwidth = lex.GetString();
  516.         } else if (token == "\\paperheight") {
  517.             lex.next();
  518.             params.paperheight = lex.GetString();
  519.         } else if (token == "\\leftmargin") {
  520.             lex.next();
  521.             params.leftmargin = lex.GetString();
  522.         } else if (token == "\\topmargin") {
  523.             lex.next();
  524.             params.topmargin = lex.GetString();
  525.         } else if (token == "\\rightmargin") {
  526.             lex.next();
  527.             params.rightmargin = lex.GetString();
  528.         } else if (token == "\\bottommargin") {
  529.             lex.next();
  530.             params.bottommargin = lex.GetString();
  531.         } else if (token == "\\headheight") {
  532.             lex.next();
  533.             params.headheight = lex.GetString();
  534.         } else if (token == "\\headsep") {
  535.             lex.next();
  536.             params.headsep = lex.GetString();
  537.         } else if (token == "\\footskip") {
  538.             lex.next();
  539.             params.footskip = lex.GetString();
  540.         } else if (token == "\\paperfontsize") {
  541.             lex.nextToken();
  542.             params.fontsize = lex.GetString();
  543.             params.fontsize.strip();
  544.         } else if (token == "\\papercolumns") {
  545.             lex.nextToken();
  546.             params.columns = lex.GetInteger();
  547.         } else if (token == "\\papersides") {
  548.             lex.nextToken();
  549.             params.sides = lex.GetInteger();
  550.         } else if (token == "\\paperpagestyle") {
  551.                 lex.nextToken();
  552.             params.pagestyle = lex.GetString();
  553.             params.pagestyle.strip();
  554.         } else if (token == "\\bullet") {
  555.             lex.nextToken();
  556.             int index = lex.GetInteger();
  557.             lex.nextToken();
  558.             int temp_int = lex.GetInteger();
  559.             params.user_defined_bullets[index].setFont(temp_int);
  560.             params.temp_bullets[index].setFont(temp_int);
  561.             lex.nextToken();
  562.             temp_int = lex.GetInteger();
  563.             params.user_defined_bullets[index].setCharacter(temp_int);
  564.             params.temp_bullets[index].setCharacter(temp_int);
  565.             lex.nextToken();
  566.             temp_int = lex.GetInteger();
  567.             params.user_defined_bullets[index].setSize(temp_int);
  568.             params.temp_bullets[index].setSize(temp_int);
  569.             lex.nextToken();
  570.             LString temp_str = lex.GetString();
  571.             if (temp_str != "\\end_bullet") {
  572.                 // this element isn't really necessary for
  573.                 // parsing but is easier for humans
  574.                 // to understand bullets. Put it back and
  575.                 // set a debug message?
  576.                 lex.printError("\\end_bullet expected, got" + temp_str);
  577.                 //how can I put it back?
  578.             }
  579.         } else if (token == "\\bulletLaTeX") {
  580.             lex.nextToken();
  581.             int index = lex.GetInteger();
  582.             lex.next();
  583.             LString temp_str = lex.GetString(), sum_str;
  584.             while (temp_str != "\\end_bullet") {
  585.                 // this loop structure is needed when user
  586.                 // enters an empty string since the first
  587.                 // thing returned will be the \\end_bullet
  588.                 // OR
  589.                 // if the LaTeX entry has spaces. Each element
  590.                 // therefore needs to be read in turn
  591.                 sum_str += temp_str;
  592.                 lex.next();
  593.                 temp_str = lex.GetString();
  594.             }
  595.             params.user_defined_bullets[index].setText(sum_str);
  596.             params.temp_bullets[index].setText(sum_str);
  597.         } else if (token == "\\secnumdepth") {
  598.             lex.nextToken();
  599.             params.secnumdepth = lex.GetInteger();
  600.         } else if (token == "\\tocdepth") {
  601.             lex.nextToken();
  602.             params.tocdepth = lex.GetInteger();
  603.         } else if (token == "\\baselinestretch") { // now obsolete
  604.             lex.nextToken(); // should not be used directly
  605.             // anymore.
  606.             // Will probably keep a kind of support just for
  607.             // compability.
  608.             params.spacing.set(Spacing::Other, lex.GetFloat());
  609.         } else if (token == "\\spacing") {
  610.             lex.nextToken();
  611.             LString tmp = lex.GetString().strip();
  612.             if (tmp == "single") {
  613.                 params.spacing.set(Spacing::Single);
  614.             } else if (tmp == "onehalf") {
  615.                 params.spacing.set(Spacing::Onehalf);
  616.             } else if (tmp == "double") {
  617.                 params.spacing.set(Spacing::Double);
  618.             } else if (tmp == "other") {
  619.                 lex.nextToken();
  620.                 params.spacing.set(Spacing::Other,
  621.                            lex.GetFloat());
  622.             } else {
  623.                 lex.printError("Unknown spacing token: '$$Token'");
  624.             }
  625.         } else if (token == "\\float_placement") {
  626.             lex.nextToken();
  627.             params.float_placement = lex.GetString();
  628.         } else if (token == "\\cursor") {
  629.             // this is obsolete, so we just skip it.
  630.             lex.nextToken();
  631.         } else if (token == "\\family") { 
  632.             lex.next();
  633.             font.setLyXFamily(lex.GetString());
  634.         } else if (token == "\\series") {
  635.             lex.next();
  636.             font.setLyXSeries(lex.GetString());
  637.         } else if (token == "\\shape") {
  638.             lex.next();
  639.             font.setLyXShape(lex.GetString());
  640.         } else if (token == "\\size") {
  641.             lex.next();
  642.             font.setLyXSize(lex.GetString());
  643.         } else if (token == "\\latex") {
  644.             lex.next();
  645.             LString tok = lex.GetString();
  646.             // This is dirty, but gone with LyX3. (Asger)
  647.             if (tok == "no_latex")
  648.                 font.setLatex(LyXFont::OFF);
  649.             else if (tok == "latex")
  650.                 font.setLatex(LyXFont::ON);
  651.             else if (tok == "default")
  652.                 font.setLatex(LyXFont::INHERIT);
  653.             else
  654.                 lex.printError("Unknown LaTeX font flag "
  655.                            "`$$Token'");
  656.         } else if (token == "\\emph") {
  657.             lex.next();
  658.             font.setEmph(font.setLyXMisc(lex.GetString()));
  659.         } else if (token == "\\bar") {
  660.             lex.next();
  661.             LString tok = lex.GetString();
  662.             // This is dirty, but gone with LyX3. (Asger)
  663.             if (tok == "under")
  664.                 font.setUnderbar(LyXFont::ON);
  665.             else if (tok == "no")
  666.                 font.setUnderbar(LyXFont::OFF);
  667.             else if (tok == "default")
  668.                 font.setUnderbar(LyXFont::INHERIT);
  669.             else
  670.                 lex.printError("Unknown bar font flag "
  671.                            "`$$Token'");
  672.         } else if (token == "\\noun") {
  673.             lex.next();
  674.             font.setNoun(font.setLyXMisc(lex.GetString()));
  675.         } else if (token == "\\color") {
  676.             lex.next();
  677.             font.setLyXColor(lex.GetString());
  678.         } else if (token == "\\align") {
  679.             tmpret = lex.FindToken(string_align);
  680.             if (tmpret == -1) tmpret++;
  681.             if (tmpret != LYX_LAYOUT_DEFAULT) {
  682.                 tmpret2 = 1;
  683.                 for (; tmpret>0; tmpret--)
  684.                     tmpret2 = tmpret2 * 2;
  685.                 par->align = tmpret2;
  686.             }
  687.         } else if (token == "\\added_space_top"){
  688.             lex.nextToken();
  689.             par->added_space_top = lex.GetString();
  690.         } else if (token == "\\added_space_bottom") {
  691.             lex.nextToken();
  692.             par->added_space_bottom = lex.GetString();
  693.                 } else if (token == "\\pextra_type") {
  694.                         lex.nextToken();
  695.                         par->pextra_type = lex.GetInteger();
  696.                 } else if (token == "\\pextra_width") {
  697.                         lex.nextToken();
  698.             par->pextra_width = lex.GetString();
  699.                 } else if (token == "\\pextra_widthp") {
  700.                         lex.nextToken();
  701.             par->pextra_widthp = lex.GetString();
  702.                 } else if (token == "\\pextra_alignment") {
  703.                         lex.nextToken();
  704.                         par->pextra_alignment = lex.GetInteger();
  705.                 } else if (token == "\\pextra_hfill") {
  706.                         lex.nextToken();
  707.                         par->pextra_hfill = lex.GetInteger();
  708.                 } else if (token == "\\pextra_start_minipage") {
  709.                         lex.nextToken();
  710.                         par->pextra_start_minipage = lex.GetInteger();
  711.         } else if (token == "\\labelwidthstring") {
  712.             lex.EatLine();
  713.             par->labelwidthstring = lex.GetString();
  714.             /* do not delete this token, it is still needed! */ 
  715.         } else if (token == "\\end_inset") {
  716.             /* simple ignore this. The insets do not have
  717.              *  to read this */
  718.             // but insets should read it, it is a part of
  719.             //the inset isn't it? Lgb.
  720.         } else if (token == "\\begin_inset") {
  721.             lex.next();
  722.             tmptok = lex.GetString();
  723.             /* test the different insets */ 
  724.             if (tmptok == "Quotes") {
  725.                 inset = new InsetQuotes;
  726.                 inset->Read(lex);
  727.                 par->InsertChar(pos, LYX_META_INSET); 
  728.                 par->InsertInset(pos, inset);
  729.                 par->SetFont(pos, font);
  730.                 pos++;
  731.             } else if (tmptok == "\\i") {
  732.                 inset = new InsetLatexAccent;
  733.                 inset->Read(lex);
  734.                 par->InsertChar(pos, LYX_META_INSET); 
  735.                 par->InsertInset(pos, inset);
  736.                 par->SetFont(pos, font);
  737.                 pos++;
  738.             } else if (tmptok == "FormulaMacro") {
  739.                 inset = new InsetFormulaMacro;
  740.                 inset->Read(lex);
  741.                 par->InsertChar(pos, LYX_META_INSET); 
  742.                 par->InsertInset(pos, inset);
  743.                 par->SetFont(pos, font);
  744.                 pos++;
  745.             } else if (tmptok == "Formula") {
  746.                 inset = new InsetFormula;
  747.                 inset->Read(lex);
  748.                 par->InsertChar(pos, LYX_META_INSET); 
  749.                 par->InsertInset(pos, inset);
  750.                 par->SetFont(pos, font);
  751.                 pos++;
  752.             } else if (tmptok == "Figure") {
  753.                 inset = new InsetFig(100,100, this);
  754.                 inset->Read(lex);
  755.                 par->InsertChar(pos, LYX_META_INSET); 
  756.                 par->InsertInset(pos, inset);
  757.                 par->SetFont(pos, font);
  758.                 pos++;
  759.                 //} else if (tmptok == "Label") {
  760.                 // Kept for compability. Remove in 0.13.
  761.                 //if (lex.EatLine()) {
  762.                 //LString tmp;
  763.                 //tmp += "\\label{";
  764.                 //tmp += lex.GetString();
  765.                 //tmp += '}';
  766.                 //inset = new InsetLabel(tmp);
  767.                 //par->InsertChar(pos, LYX_META_INSET); 
  768.                 //par->InsertInset(pos, inset);
  769.                 //par->SetFont(pos, font);
  770.                 //pos++;
  771.                 //}
  772.             } else if (tmptok == "Info") {
  773.                 inset = new InsetInfo;
  774.                 inset->Read(lex);
  775.                 par->InsertChar(pos, LYX_META_INSET); 
  776.                 par->InsertInset(pos, inset);
  777.                 par->SetFont(pos, font);
  778.                 pos++;
  779.             } else if (tmptok == "Include") {
  780.                 inset = new InsetInclude(LString(), this);
  781.                 inset->Read(lex);
  782.                 par->InsertChar(pos, LYX_META_INSET); 
  783.                 par->InsertInset(pos, inset);
  784.                 par->SetFont(pos, font);
  785.                 pos++;
  786.             } else if (tmptok == "LatexCommand") {
  787.                 InsetCommand inscmd;
  788.                 inscmd.Read(lex);
  789.                 if (inscmd.getCmdName()=="cite") {
  790.                     inset = new InsetCitation(inscmd.getContents(), inscmd.getOptions());
  791.                 } else if (inscmd.getCmdName()=="bibitem") {
  792.                     lex.printError("Wrong place for bibitem");
  793.                     inset = inscmd.Clone();
  794.                 } else if (inscmd.getCmdName()=="BibTeX") {
  795.                     inset = new InsetBibtex(inscmd.getContents(), inscmd.getOptions(), this);
  796.                 } else if (inscmd.getCmdName()=="index") {
  797.                     inset = new InsetIndex(inscmd.getContents());
  798.                 } else if (inscmd.getCmdName()=="include") {
  799.                     inset = new InsetInclude(inscmd.getContents(), this);
  800.                 } else if (inscmd.getCmdName()=="label") {
  801.                     inset = new InsetLabel(inscmd.getCommand());
  802.                 } else if (inscmd.getCmdName() == "ref"
  803.                        || inscmd.getCmdName() == "pageref") {
  804.                     inset = new InsetRef(inscmd, this);
  805.                 } else if (inscmd.getCmdName()=="tableofcontents") {
  806.                     inset = new InsetTOC(this);
  807.                 } else if (inscmd.getCmdName()=="listoffigures") {
  808.                     inset = new InsetLOF(this);
  809.                 } else if (inscmd.getCmdName()=="listofalgorithms") {
  810.                     inset = new InsetLOA(this);
  811.                 } else if (inscmd.getCmdName()=="listoftables") {
  812.                     inset = new InsetLOT(this);
  813.                 } else if (inscmd.getCmdName()=="printindex") {
  814.                     inset = new InsetPrintIndex(this);
  815.                 } else if (inscmd.getCmdName()=="lyxparent") {
  816.                     inset = new InsetParent(inscmd.getContents(),this);
  817.                 } else 
  818.                     // The following three are only for compatibility
  819.                     if (inscmd.getCmdName()=="-") {
  820.                         inset = new InsetSpecialChar(InsetSpecialChar::HYPHENATION);
  821.                     } else if (inscmd.getCmdName()=="@.") {
  822.                         inset = new InsetSpecialChar(InsetSpecialChar::END_OF_SENTENCE);
  823.                     } else if (inscmd.getCmdName()=="ldots") {
  824.                         inset = new InsetSpecialChar(InsetSpecialChar::LDOTS);
  825.                     } else
  826.                         inset = inscmd.Clone();
  827.                    
  828.                 if (inset) {
  829.                     par->InsertChar(pos, LYX_META_INSET);
  830.                     par->InsertInset(pos, inset);
  831.                     par->SetFont(pos, font);
  832.                     pos++;
  833.                 }
  834.             }
  835.         } else if (token == "\\InsetQuotes") {
  836.             inset = new InsetQuotes;
  837.             inset->Read(lex);
  838.             par->InsertChar(pos, LYX_META_INSET); 
  839.             par->InsertInset(pos, inset);
  840.             par->SetFont(pos, font);
  841.             pos++;
  842.         } else if (token == "\\InsetFormula") {
  843.             inset = new InsetFormula;
  844.             inset->Read(lex);
  845.             par->InsertChar(pos, LYX_META_INSET); 
  846.             par->InsertInset(pos, inset);
  847.             par->SetFont(pos, font);
  848.             pos++;
  849.         } else if (token == "\\SpecialChar") {
  850.             inset = new InsetSpecialChar;
  851.             inset->Read(lex);
  852.             par->InsertChar(pos, LYX_META_INSET); 
  853.             par->InsertInset(pos, inset);
  854.             par->SetFont(pos, font);
  855.             pos++;
  856.         } else if (token == "\\Figure") {
  857.             inset = new InsetFig(100,100, this);
  858.             inset->Read(lex);
  859.             par->InsertChar(pos, LYX_META_INSET); 
  860.             par->InsertInset(pos, inset);
  861.             par->SetFont(pos, font);
  862.             pos++;
  863.         } else if (token == "\\newline") {
  864.             par->InsertChar(pos, LYX_META_NEWLINE);
  865.             par->SetFont(pos, font);
  866.             pos++;
  867.         } else if (token == "\\LyXTable") {
  868.             par->table = new LyXTable(lex);
  869.         } else if (token == "\\hfill") {
  870.             par->InsertChar(pos, LYX_META_HFILL);
  871.             par->SetFont(pos, font);
  872.             pos++;
  873.         } else if (token == "\\protected_separator") {
  874.             par->InsertChar(pos, LYX_META_PROTECTED_SEPARATOR);
  875.             par->SetFont(pos, font);
  876.             pos++;
  877.         } else if (token == "\\bibitem") {  // ale970302
  878.                 if (!par->bibkey)
  879.                 par->bibkey = new InsetBibKey;
  880.                 par->bibkey->Read(lex);                
  881.         }else if (token == "\\backslash") {
  882.             par->InsertChar(pos, '\\');
  883.             par->SetFont(pos, font);
  884.             pos++;
  885.         }else if (token == "\\the_end") {
  886.             the_end_read = true;
  887.         } else {
  888.             // This should be insurance for the future: (Asger)
  889.             lex.printError("Unknown token `$$Token'. "
  890.                        "Inserting as text.");
  891.             int n = token.length();
  892.             for (int i=0; i < n; i++) {
  893.                 par->InsertChar(pos, token[i]);
  894.                 par->SetFont(pos, font);
  895.                 pos++;
  896.             }
  897.         }
  898.     }
  899.    
  900.     if (!return_par)
  901.         return_par = par;
  902.  
  903.     paragraph = return_par;
  904.     
  905.     return the_end_read;
  906. }
  907.  
  908.  
  909. bool Buffer::readFile(LyXLex &lex, LyXParagraph *par)
  910. {
  911.     LString token;
  912.  
  913.     if (lex.IsOK()) {
  914.         lex.next();
  915.         token = lex.GetString();
  916.         if (token == "\\lyxformat") { // the first token _must_ be...
  917.             lex.next();
  918.             format = lex.GetFloat();
  919.             if (format > 1) {
  920.                 if (LYX_FORMAT - format > 0.05) {
  921.                     lyxerr.print(LString(_("Warning: need lyxformat ")) + int(LYX_FORMAT) + LString(_(" but found ")) + int(format));
  922.                 }
  923.                 if (format - LYX_FORMAT > 0.05) {
  924.                     lyxerr.print(LString(_("ERROR: need lyxformat ")) + int(LYX_FORMAT) + LString(_(" but found ")) + int(format));
  925.  
  926.                 }
  927.                 bool the_end = readLyXformat2(lex, par);
  928.                 // Formats >= 2.13 support "\the_end" marker
  929.                 if (format < 2.13)
  930.                     the_end = true;
  931.                                 // Formats >= 2.14 changed papersize stuff
  932.                                 if (format < 2.14) {
  933.                                         setOldPaperStuff();
  934.                                 } else {
  935.                                         setPaperStuff();
  936.                                 }
  937.                 if (!the_end)
  938.                     WriteAlert(_("Warning!"),
  939.                            _("Reading of document is not complete"),
  940.                            _("Maybe the document is truncated"));
  941.                 // We simulate a safe reading anyways to allow
  942.                 // users to take the chance... (Asger)
  943.                 return true;
  944.             } // format < 1
  945.             else {
  946.                 WriteAlert(_("ERROR!"),
  947.                        _("Old LyX file format found. "
  948.                          "Use LyX 0.10.x to read this!"));
  949.                 return false;
  950.             }
  951.  
  952.         } else { // "\\lyxformat" not found
  953.             WriteAlert(_("ERROR!"), _("Not a LyX file!"));
  954.         }
  955.     } else
  956.         WriteAlert(_("ERROR!"), _("Unable to read file!"));
  957.     return false;
  958. }
  959.                 
  960.  
  961. // Returns false if unsuccesful
  962. bool Buffer::writeFile(LString const & filename, bool flag)
  963. {
  964.     // if flag is false writeFile will not create any GUI
  965.     // warnings, only stderr.
  966.     // Needed for autosave in background or panic save (Matthias 120496)
  967.  
  968.     if (read_only && (filename == this->filename)) {
  969.         // Here we should come with a question if we should
  970.         // perform the write anyway.
  971.         if (flag)
  972.             lyxerr.print(_("Error! Document is read-only: ") + filename);
  973.         else
  974.             WriteAlert(_("Error! Document is read-only: "), filename);
  975.         return false;
  976.     }
  977.  
  978.     FileInfo finfo(filename);
  979.     if (finfo.exist() && !finfo.writable()) {
  980.         // Here we should come with a question if we should
  981.         // try to do the save anyway. (i.e. do a chmod first)
  982.         if (flag)
  983.             lyxerr.print(_("Error! Cannot write file: ") + filename);
  984.         else
  985.             WriteFSAlert(_("Error! Cannot write file: "), filename);
  986.         return false;
  987.     }
  988.  
  989.     FilePtr file(filename, FilePtr::truncate);
  990.     if (!file()) {
  991.         if (flag)
  992.             lyxerr.print(_("Error! Cannot write file: ") + filename);
  993.         else
  994.             WriteFSAlert(_("Error! Cannot write file: "), filename);
  995.         return false;
  996.     }
  997.     // The top of the file should not be written by params.
  998.     // collect some very important information
  999.     LString userName(getUserName()) ;
  1000.  
  1001.     // write out a comment in the top of the file
  1002.     fprintf(file,
  1003.         "#This file was created by <%s> %s",
  1004.         userName.c_str(),(char*)date());
  1005.     fprintf(file,
  1006.         "#LyX 0.12 (C) 1995-1998 Matthias Ettrich"
  1007.         " and the LyX Team\n");
  1008.     
  1009.     // at the very beginning the used lyx format
  1010.     fprintf(file, "\\lyxformat %.2f\n", LYX_FORMAT);
  1011.  
  1012.     // now write out the buffer parameters.
  1013.     params.writeFile(file);
  1014.  
  1015.     char footnoteflag = 0;
  1016.     char depth = 0;
  1017.  
  1018.     // this will write out all the paragraphs
  1019.     // using recursive descent.
  1020.     paragraph->writeFile(file, params, footnoteflag, depth);
  1021.  
  1022.     // Write marker that shows file is complete
  1023.     fprintf(file, "\n\\the_end\n");
  1024.     if (file.close()) {
  1025.         if (flag)
  1026.             lyxerr.print(_("Error! Could not close file properly: ")
  1027.                      +    filename);
  1028.         else
  1029.             WriteFSAlert(_("Error! Could not close file properly: "),
  1030.                      filename);
  1031.         return false;
  1032.     }
  1033.     return true;
  1034. }
  1035.  
  1036.  
  1037. void Buffer::writeFileAscii(LString const & filename, int linelen) 
  1038. {
  1039.     FilePtr    file(filename, FilePtr::write);
  1040.     LyXFont
  1041.         font1, font2;
  1042.     Inset
  1043.         *inset;
  1044.     LyXParagraph
  1045.         *par = paragraph;
  1046.     char
  1047.         c,
  1048.         footnoteflag = 0,
  1049.         depth = 0;
  1050.  
  1051.     LString
  1052.         fname1,
  1053.         tmp;
  1054.     
  1055.     int
  1056.         i,j,h,
  1057.         ltype=0,
  1058.         ltype_depth=0,
  1059.         noparbreak=0,
  1060.         islatex=0,
  1061.         *clen=NULL,
  1062.         actcell=0,
  1063.         actpos=0,
  1064.         cell=0,
  1065.             cells=0,
  1066.             currlinelen=0;
  1067.     long
  1068.         fpos=0;
  1069.     bool
  1070.         ref_printed = false;
  1071.    
  1072.    
  1073.     if (!file()) {
  1074.         WriteFSAlert(_("Error: Cannot write file:"), filename);
  1075.         return;
  1076.     }
  1077.     fname1=TmpFileName();
  1078.     while (par) {
  1079.         noparbreak = 0;
  1080.         islatex = 0;
  1081.         if (par->footnoteflag != LyXParagraph::NO_FOOTNOTE ||
  1082.             !par->previous ||
  1083.             par->previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
  1084.      
  1085.             /* begins a footnote environment ? */ 
  1086.             if (footnoteflag != par->footnoteflag) {
  1087.                 footnoteflag = par->footnoteflag;
  1088.                 if (footnoteflag) {
  1089.                     j=strlen(string_footnotekinds[par->footnotekind])+4;
  1090.                     if (currlinelen+j > linelen)
  1091.                         fprintf(file,"\n");
  1092.                     fprintf(file, "([%s] ", 
  1093.                         string_footnotekinds[par->footnotekind]);
  1094.                     currlinelen += j;
  1095.                 }
  1096.             }
  1097.      
  1098.             /* begins or ends a deeper area ?*/ 
  1099.             if (depth != par->depth) {
  1100.                 if (par->depth > depth) {
  1101.                     while (par->depth > depth) {
  1102.                         depth++;
  1103.                     }
  1104.                 }
  1105.                 else {
  1106.                     while (par->depth < depth) {
  1107.                         depth--;
  1108.                     }
  1109.                 }
  1110.             }
  1111.      
  1112.             /* First write the layout */
  1113.             tmp = lyxstyle.NameOfLayout(params.textclass,par->layout);
  1114.             if (tmp == "Itemize") {
  1115.                 ltype = 1;
  1116.                 ltype_depth = depth+1;
  1117.             } else if (tmp =="Enumerate") {
  1118.                 ltype = 2;
  1119.                 ltype_depth = depth+1;
  1120.             } else if (strstr(tmp.c_str(),"ection")) {
  1121.                 ltype = 3;
  1122.                 ltype_depth = depth+1;
  1123.             } else if (strstr(tmp.c_str(),"aragraph")) {
  1124.                 ltype = 4;
  1125.                 ltype_depth = depth+1;
  1126.             } else if (tmp == "Description") {
  1127.                 ltype = 5;
  1128.                 ltype_depth = depth+1;
  1129.             } else if (tmp == "Abstract") {
  1130.                 ltype = 6;
  1131.                 ltype_depth = 0;
  1132.             } else if (tmp == "Bibliography") {
  1133.                 ltype = 7;
  1134.                 ltype_depth = 0;
  1135.             } else {
  1136.                 ltype = 0;
  1137.                 ltype_depth = 0;
  1138.             }
  1139.      
  1140.             /* maybe some vertical spaces */ 
  1141.  
  1142.             /* the labelwidthstring used in lists */ 
  1143.      
  1144.             /* some lines? */ 
  1145.      
  1146.             /* some pagebreaks? */ 
  1147.      
  1148.             /* noindent ? */ 
  1149.      
  1150.             /* what about the alignment */ 
  1151.         }
  1152.         else {
  1153.             /* dummy layout, that means a footnote ended */ 
  1154.             footnoteflag = LyXParagraph::NO_FOOTNOTE;
  1155.             fprintf(file, ") ");
  1156.             noparbreak = 1;
  1157.         }
  1158.       
  1159.         /* It might be a table */ 
  1160.         if (par->table){
  1161.             if (!lyxrc->ascii_roff_command.empty() &&
  1162.                             lyxrc->ascii_roff_command != "none") {
  1163.                 RoffAsciiTable(file,par);
  1164.                 par = par->next;
  1165.                 continue;
  1166.             }
  1167.             cell = 1;
  1168.                         actcell = 0;
  1169.             cells = par->table->columns;
  1170.             clen = new int [cells];
  1171.             memset(clen,0,sizeof(int)*cells);
  1172.             for (i = 0, j = 0, h=1; i < par->last; i++, h++) {
  1173.                 c = par->GetChar(i);
  1174.                 if (c == LYX_META_INSET) {
  1175.                     if ((inset = par->GetInset(i))) {
  1176.                         FilePtr fp(fname1,
  1177.                                FilePtr::write);
  1178.                         if (!fp()) {
  1179.                             WriteFSAlert(_("Error: Cannot open temporary file:"), fname1);
  1180.                             return;
  1181.                         }
  1182.                         inset->Latex(fp,-1);
  1183.                         h += ftell(fp) - 1;
  1184.                         remove(fname1.c_str());
  1185.                     }
  1186.                 } else if (c == LYX_META_NEWLINE) {
  1187.                     if (clen[j] < h)
  1188.                         clen[j] = h;
  1189.                     h = 0;
  1190.                     j = (++j) % par->table->NumberOfCellsInRow(actcell);
  1191.                                         actcell++;
  1192.                 }
  1193.             }
  1194.             if (clen[j] < h)
  1195.                 clen[j] = h;
  1196.         }
  1197.       
  1198.         font1 = LyXFont(LyXFont::ALL_INHERIT);
  1199.                 actcell=0;
  1200.         for (i = 0,actpos=1; i < par->last; i++, actpos++) {
  1201.             if (!i && !footnoteflag && !noparbreak){
  1202.                 fprintf(file, "\n\n");
  1203.                 for(j=0; j<depth; j++)
  1204.                     fprintf(file, "  ");
  1205.                 currlinelen = depth*2;
  1206.                 switch(ltype) {
  1207.                 case 0: /* Standart */
  1208.                 case 4: /* (Sub)Paragraph */
  1209.                                 case 5: /* Description */
  1210.                     break;
  1211.                 case 6: /* Abstract */
  1212.                     fprintf(file, "Abstract\n\n");
  1213.                     break;
  1214.                 case 7: /* Bibliography */
  1215.                     if (!ref_printed) {
  1216.                         fprintf(file, "References\n\n");
  1217.                         ref_printed = true;
  1218.                     }
  1219.                     break;
  1220.                 default:
  1221.                     fprintf(file,"%s ",par->labelstring.c_str());
  1222.                     break;
  1223.                 }
  1224.                 if (ltype_depth > depth) {
  1225.                     for(j=ltype_depth-1; j>depth; j--)
  1226.                         fprintf(file, "  ");
  1227.                     currlinelen += (ltype_depth-depth)*2;
  1228.                 }
  1229.                 if (par->table) {
  1230.                     for(j=0;j<cells;j++) {
  1231.                         fputc('+',file);
  1232.                         for(h=0; h<(clen[j]+1); h++)
  1233.                             fputc('-',file);
  1234.                     }
  1235.                     fprintf(file,"+\n");
  1236.                     for(j=0; j<depth; j++)
  1237.                         fprintf(file, "  ");
  1238.                     currlinelen = depth*2;
  1239.                     if (ltype_depth > depth) {
  1240.                         for(j=ltype_depth; j>depth; j--)
  1241.                             fprintf(file, "  ");
  1242.                         currlinelen += (ltype_depth-depth)*2;
  1243.                     }
  1244.                     fprintf(file,"| ");
  1245.                 }
  1246.             }
  1247.             font2 = par->GetFontSettings(i);
  1248.             if (font1.latex() != font2.latex()) {
  1249.                 if (font2.latex() == LyXFont::OFF)
  1250.                     islatex = 0;
  1251.                 else
  1252.                     islatex = 1;
  1253.             }
  1254.             else {
  1255.                 islatex = 0;
  1256.             }
  1257.             c = par->GetChar(i);
  1258.             if (islatex)
  1259.                 continue;
  1260.             switch (c) {
  1261.             case LYX_META_INSET:
  1262.                 if ((inset = par->GetInset(i))) {
  1263.                     fpos = ftell(file);
  1264.                     inset->Latex(file,-1);
  1265.                     currlinelen += (ftell(file) - fpos);
  1266.                     actpos += (ftell(file) - fpos) - 1;
  1267.                 }
  1268.                 break;
  1269.             case LYX_META_NEWLINE:
  1270.                 if (par->table) {
  1271.                     if (par->table->NumberOfCellsInRow(actcell) <= cell) {
  1272.                         for(j=actpos;j<clen[cell-1];j++)
  1273.                             fputc(' ',file);
  1274.                         fprintf(file," |\n");
  1275.                         for(j=0; j<depth; j++)
  1276.                             fprintf(file, "  ");
  1277.                         currlinelen = depth*2;
  1278.                         if (ltype_depth > depth) {
  1279.                             for(j=ltype_depth; j>depth; j--)
  1280.                                 fprintf(file, "  ");
  1281.                             currlinelen += (ltype_depth-depth)*2;
  1282.                         }
  1283.                         for(j=0;j<cells;j++) {
  1284.                             fputc('+',file);
  1285.                             for(h=0; h<(clen[j]+1); h++)
  1286.                                 fputc('-',file);
  1287.                         }
  1288.                         fprintf(file,"+\n");
  1289.                         for(j=0; j<depth; j++)
  1290.                             fprintf(file, "  ");
  1291.                         currlinelen = depth*2;
  1292.                         if (ltype_depth > depth) {
  1293.                             for(j=ltype_depth; j>depth; j--)
  1294.                                 fprintf(file, "  ");
  1295.                             currlinelen += (ltype_depth-depth)*2;
  1296.                         }
  1297.                         fprintf(file,"| ");
  1298.                         cell = 1;
  1299.                     } else {
  1300.                         for(j=actpos; j<clen[cell-1]; j++)
  1301.                             fputc(' ',file);
  1302.                         fprintf(file, " | ");
  1303.                         cell++;
  1304.                     }
  1305.                                         actcell++;
  1306.                     currlinelen = actpos = 0;
  1307.                 } else {
  1308.                     fprintf(file, "\n");
  1309.                     for(j=0; j<depth; j++)
  1310.                         fprintf(file, "  ");
  1311.                     currlinelen = depth*2;
  1312.                     if (ltype_depth > depth) {
  1313.                         for(j=ltype_depth; j>depth; j--)
  1314.                             fprintf(file, "  ");
  1315.                         currlinelen += (ltype_depth-depth)*2;
  1316.                     }
  1317.                 }
  1318.                 break;
  1319.             case LYX_META_HFILL: 
  1320.                 fprintf(file, "\t");
  1321.                 break;
  1322.             case LYX_META_PROTECTED_SEPARATOR:
  1323.                 fprintf(file, " ");
  1324.                 break;
  1325.             case '\\': 
  1326.                 fprintf(file, "\\");
  1327.                 break;
  1328.             default:
  1329.                 if (currlinelen > (linelen-10) \
  1330.                                     && c==' ' && (i+2 < par->last)) {
  1331.                     fprintf(file, "\n");
  1332.                     for(j=0; j<depth; j++)
  1333.                         fprintf(file, "  ");
  1334.                     currlinelen = depth*2;
  1335.                     if (ltype_depth > depth) {
  1336.                         for(j=ltype_depth; j>depth; j--)
  1337.                             fprintf(file, "  ");
  1338.                         currlinelen += (ltype_depth-depth)*2;
  1339.                     }
  1340.                 } else if (c != '\0')
  1341.                     fprintf(file, "%c", c);
  1342.                 else if (c == '\0')
  1343.                     lyxerr.debug("writeAsciiFile: NULL char in structure.");
  1344.                 currlinelen++;
  1345.                 break;
  1346.             }
  1347.         }
  1348.         if (par->table) {
  1349.             for(j=actpos;j<clen[cell-1];j++)
  1350.                 fputc(' ',file);
  1351.             fprintf(file," |\n");
  1352.             for(j=0; j<depth; j++)
  1353.                 fprintf(file, "  ");
  1354.             currlinelen = depth*2;
  1355.             if (ltype_depth > depth) {
  1356.                 for(j=ltype_depth; j>depth; j--)
  1357.                     fprintf(file, "  ");
  1358.                 currlinelen += (ltype_depth-depth)*2;
  1359.             }
  1360.             for(j=0;j<cells;j++) {
  1361.                 fputc('+',file);
  1362.                 for(h=0; h<(clen[j]+1); h++)
  1363.                     fputc('-',file);
  1364.             }
  1365.             fprintf(file,"+\n");
  1366.             delete [] clen;    
  1367.         }      
  1368.         par = par->next;
  1369.     }
  1370.    
  1371.     fprintf(file, "\n");
  1372. }
  1373.  
  1374.  
  1375. void Buffer::makeLaTeXFile(LString const & filename, 
  1376.                LString const & original_path,
  1377.                bool nice, bool only_body)
  1378. {
  1379.     lyxerr.debug("makeLaTeXFile...", Error::LATEX);
  1380.     params.textclass = GetCurrentTextClass();
  1381.     niceFile = nice; // this will be used by Insetincludes.
  1382.     if (nice) 
  1383.         tex_code_break_column = lyxrc->ascii_linelen;
  1384.     else
  1385.         tex_code_break_column = 0;
  1386.  
  1387.         LyXTextClass *tclass = lyxstyle.TextClass(params.textclass);
  1388.   
  1389.     FilePtr file(filename, FilePtr::write);
  1390.     if (!file()) {
  1391.         WriteFSAlert(_("Error: Cannot write file:"),filename);
  1392.         return;
  1393.     }
  1394.  
  1395.     // validate the buffer.
  1396.     lyxerr.debug("  Validating buffer...", Error::LATEX);
  1397.     LaTeXFeatures features(tclass->number_of_defined_layouts);
  1398.     validate(features);
  1399.     lyxerr.debug("  Buffer validation done.", Error::LATEX);
  1400.     
  1401.     texrow.reset();
  1402.     // The starting paragraph of the coming rows is the 
  1403.     // first paragraph of the document. (Asger)
  1404.     texrow.start(paragraph, 0);
  1405.  
  1406.     LString userName(getUserName());
  1407.     LString LFile;
  1408.     
  1409.     if (!only_body) {
  1410.         LFile += "%% This LaTeX-file was created by <";
  1411.         LFile += userName + "> " + (char*)date();
  1412.         LFile += "%% LyX 0.12 (C) 1995-1998 by Matthias Ettrich and the LyX Team\n";
  1413.         LFile += "\n%% Do not edit this file unless you know what you are doing.\n";
  1414.         texrow.newline();
  1415.         texrow.newline();
  1416.         texrow.newline();
  1417.         texrow.newline();
  1418.     }
  1419.     lyxerr.debug("lyx header finished");
  1420.     // There are a few differences between nice LaTeX and usual files:
  1421.     // usual is \batchmode, uses \listfiles and has a 
  1422.     // special input@path to allow the including of figures
  1423.     // with either \input or \includegraphics (what figinsets do).
  1424.     // batchmode is not set if there is a tex_code_break_column.
  1425.     // In this case somebody is interested in the generated LaTeX,
  1426.     // so this is OK. input@path is set when the actual parameter
  1427.     // original_path is set. This is done for usual tex-file, but not
  1428.     // for nice-latex-file. (Matthias 250696)
  1429.     if (!only_body) {
  1430.         if (!nice){
  1431.             // code for usual, NOT nice-latex-file
  1432.             LFile += "\\batchmode\n"; // changed
  1433.             // from \nonstopmode
  1434.             texrow.newline();
  1435.             LFile += "\\listfiles\n";
  1436.             texrow.newline();
  1437.         }
  1438.         if (!original_path.empty()) {
  1439.             LFile += "\\makeatletter\n";
  1440.             texrow.newline();
  1441.             LFile += "\\def\\input@path{{" + original_path
  1442.                  + "/}}\n";
  1443.             texrow.newline();
  1444.             LFile += "\\makeatother\n";
  1445.             texrow.newline();
  1446.         }
  1447.         
  1448.         LFile += "\\documentclass";
  1449.         
  1450.         LString options; // the document class options.
  1451.         
  1452.         if (tclass->opt_fontsize.tokenPos('|',params.fontsize) >= 0) {
  1453.             // only write if existing in list (and not default)
  1454.             options += params.fontsize;
  1455.             options += "pt,";
  1456.         }
  1457.         
  1458.         
  1459.         if (!params.use_geometry &&
  1460.             (params.paperpackage == PACKAGE_NONE)) {
  1461.             switch (params.papersize) {
  1462.             case PAPER_A4PAPER:
  1463.                 options += "a4paper,";
  1464.                 break;
  1465.             case PAPER_USLETTER:
  1466.                 options += "letterpaper,";
  1467.                 break;
  1468.             case PAPER_A5PAPER:
  1469.                 options += "a5paper,";
  1470.                 break;
  1471.             case PAPER_B5PAPER:
  1472.                 options += "b5paper,";
  1473.                 break;
  1474.             case PAPER_EXECUTIVEPAPER:
  1475.                 options += "executivepaper,";
  1476.                 break;
  1477.             case PAPER_LEGALPAPER:
  1478.                 options += "legalpaper,";
  1479.                 break;
  1480.             }
  1481.         }
  1482.  
  1483.         // if needed
  1484.         if (params.sides != tclass->sides) {
  1485.             if (params.sides == 2)
  1486.                 options += "twoside,";
  1487.             else
  1488.                 options += "oneside,";
  1489.         }
  1490.  
  1491.         // if needed
  1492.         if (params.columns != tclass->columns) {
  1493.             if (params.columns == 2)
  1494.                 options += "twocolumn,";
  1495.             else
  1496.                 options += "onecolumn,";
  1497.         }
  1498.  
  1499.         if (!params.use_geometry && params.orientation == ORIENTATION_LANDSCAPE)
  1500.             options += "landscape,";
  1501.         
  1502.         // language should be a parameter to \documentclass
  1503.         if (params.language != "default") {
  1504.             options += params.language + ',';
  1505.         }
  1506.         
  1507.         // the user-defined options
  1508.         if (!params.options.empty()) {
  1509.             options += params.options + ',';
  1510.         }
  1511.         
  1512.         if (!options.empty()){
  1513.             options.strip(',');
  1514.             LFile += '[';
  1515.             LFile += options;
  1516.             LFile += ']';
  1517.         }
  1518.         
  1519.         LFile += '{';
  1520.         LFile += lyxstyle.LatexnameOfClass(params.textclass);
  1521.         LFile += "}\n";
  1522.         texrow.newline();
  1523.         // end of \documentclass defs
  1524.         
  1525.         // this one is not per buffer
  1526.         if (lyxrc->fontenc != "default") {
  1527.             LFile += "\\usepackage[" + lyxrc->fontenc
  1528.                  + "]{fontenc}\n";
  1529.             texrow.newline();
  1530.         }
  1531.         if (params.inputenc != "default") {
  1532.             LFile += "\\usepackage[" + params.inputenc
  1533.                  + "]{inputenc}\n";
  1534.             texrow.newline();
  1535.         }
  1536.         if (params.fonts != "default") {
  1537.             LFile += "\\usepackage{" + params.fonts + "}\n";
  1538.             texrow.newline();
  1539.         }
  1540.         
  1541.         /* at the very beginning the text parameters */
  1542.         if (params.paperpackage != PACKAGE_NONE) {
  1543.             switch (params.paperpackage) {
  1544.             case PACKAGE_A4:
  1545.                 LFile += "\\usepackage{a4}\n";
  1546.                 texrow.newline();
  1547.                 break;
  1548.             case PACKAGE_A4WIDE:
  1549.                 LFile += "\\usepackage{a4wide}\n";
  1550.                 texrow.newline();
  1551.                 break;
  1552.             case PACKAGE_WIDEMARGINSA4:
  1553.                 LFile += "\\usepackage[widemargins]{a4}\n";
  1554.                 texrow.newline();
  1555.                 break;
  1556.             }
  1557.         }
  1558.         if (params.use_geometry) {
  1559.             LFile += "\\usepackage{geometry}\n";
  1560.             texrow.newline();
  1561.             LFile += "\\geometry{verbose";
  1562.             if (params.orientation == ORIENTATION_LANDSCAPE)
  1563.                 LFile += ",landscape";
  1564.             switch (params.papersize2) {
  1565.             case VM_PAPER_CUSTOM:
  1566.                 if (!params.paperwidth.empty())
  1567.                     LFile += ",paperwidth="
  1568.                          + params.paperwidth;
  1569.                 if (!params.paperheight.empty())
  1570.                     LFile += ",paperheight="
  1571.                          + params.paperheight;
  1572.                 break;
  1573.             case VM_PAPER_USLETTER:
  1574.                 LFile += ",letterpaper";
  1575.                 break;
  1576.             case VM_PAPER_USLEGAL:
  1577.                 LFile += ",legalpaper";
  1578.                 break;
  1579.             case VM_PAPER_USEXECUTIVE:
  1580.                 LFile += ",executivepaper";
  1581.                 break;
  1582.             case VM_PAPER_A3:
  1583.                 LFile += ",a3paper";
  1584.                 break;
  1585.             case VM_PAPER_A4:
  1586.                 LFile += ",a4paper";
  1587.                 break;
  1588.             case VM_PAPER_A5:
  1589.                 LFile += ",a5paper";
  1590.                 break;
  1591.             case VM_PAPER_B3:
  1592.                 LFile += ",b3paper";
  1593.                 break;
  1594.             case VM_PAPER_B4:
  1595.                 LFile += ",b4paper";
  1596.                 break;
  1597.             case VM_PAPER_B5:
  1598.                 LFile += ",b5paper";
  1599.                 break;
  1600.             }
  1601.             if (!params.topmargin.empty())
  1602.                 LFile += ",tmargin=" + params.topmargin;
  1603.             if (!params.bottommargin.empty())
  1604.                 LFile += ",bmargin=" + params.bottommargin;
  1605.             if (!params.leftmargin.empty())
  1606.                 LFile += ",lmargin=" + params.leftmargin;
  1607.             if (!params.rightmargin.empty())
  1608.                 LFile += ",rmargin=" + params.rightmargin;
  1609.             if (!params.headheight.empty())
  1610.                 LFile += ",headheight=" + params.headheight;
  1611.             if (!params.headsep.empty())
  1612.                 LFile += ",headsep=" + params.headsep;
  1613.             if (!params.footskip.empty())
  1614.                 LFile += ",footskip=" + params.footskip;
  1615.             LFile += "}\n";
  1616.             texrow.newline();
  1617.         }
  1618.         if (params.use_amsmath
  1619.             && !lyxstyle.LatexnameOfClass(params.textclass).prefixIs("ams")) {
  1620.             LFile += "\\usepackage{amsmath}\n";
  1621.         }
  1622.  
  1623.         if (tclass->opt_pagestyle.tokenPos('|',params.pagestyle) >= 0) {
  1624.             if (params.pagestyle == "fancy") {
  1625.                 LFile += "\\usepackage{fancyhdr}\n";
  1626.                 texrow.newline();
  1627.             }
  1628.             LFile += "\\pagestyle{" + params.pagestyle + "}\n";
  1629.             texrow.newline();
  1630.         }
  1631.  
  1632.         // We try to load babel late, in case it interferes
  1633.         // with other packages.
  1634.         if (params.language != "default") {
  1635.             LFile += "\\usepackage{babel}\n";
  1636.             texrow.newline();
  1637.         }
  1638.  
  1639.         if (params.secnumdepth != tclass->secnumdepth) {
  1640.             LFile += "\\setcounter{secnumdepth}{";
  1641.             LFile += params.secnumdepth;
  1642.             LFile += "}\n";
  1643.             texrow.newline();
  1644.         }
  1645.         if (params.tocdepth != tclass->tocdepth) {
  1646.             LFile += "\\setcounter{tocdepth}{";
  1647.             LFile += params.tocdepth;
  1648.             LFile += "}\n";
  1649.             texrow.newline();
  1650.         }
  1651.         
  1652.         if (params.paragraph_separation) {
  1653.             switch (params.defskip.kind()) {
  1654.             case VSpace::SMALLSKIP: 
  1655.                 LFile += "\\setlength\\parskip{\\smallskipamount}\n";
  1656.                 break;
  1657.             case VSpace::MEDSKIP:
  1658.                 LFile += "\\setlength\\parskip{\\medskipamount}\n";
  1659.                 break;
  1660.             case VSpace::BIGSKIP:
  1661.                 LFile += "\\setlength\\parskip{\\bigskipamount}\n";
  1662.                 break;
  1663.             case VSpace::LENGTH:
  1664.                 LFile += "\\setlength\\parskip{"
  1665.                      + params.defskip.length().asLatexString()
  1666.                      + "}\n";
  1667.                 break;
  1668.             default: // should never happen // Then delete it.
  1669.                 LFile += "\\setlength\\parskip{\\medskipamount}\n";
  1670.                 break;
  1671.             }
  1672.             texrow.newline();
  1673.             
  1674.             LFile += "\\setlength\\parindent{0pt}\n";
  1675.             texrow.newline();
  1676.         }
  1677.  
  1678.         // Write out what we've generated so far...and reset LFile
  1679.         fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
  1680.         LFile.erase(); 
  1681.  
  1682.         // Now insert the LyX specific LaTeX commands...
  1683.         LString preamble, tmppreamble;
  1684.  
  1685.         // The optional packages;
  1686.         preamble = features.getPackages(params);
  1687.  
  1688.         // this might be useful...
  1689.         preamble += "\n\\makeatletter\n\n";
  1690.  
  1691.         // Some macros LyX will need
  1692.         tmppreamble = features.getMacros(params);
  1693.  
  1694.         if (!tmppreamble.empty()) {
  1695.             preamble += "\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
  1696.                 "LyX specific LaTeX commands.\n"
  1697.                 + tmppreamble + '\n';
  1698.         }
  1699.  
  1700.         // the text class specific preamble 
  1701.         tmppreamble = features.getTClassPreamble(params);
  1702.         if (!tmppreamble.empty()) {
  1703.             preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
  1704.                 "Textclass specific LaTeX commands.\n"
  1705.                 + tmppreamble + '\n';
  1706.         }
  1707.  
  1708.         /* the user-defined preamble */
  1709.         if (!params.preamble.empty()) {
  1710.             preamble += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "
  1711.                 "User specified LaTeX commands.\n"
  1712.                 + params.preamble + '\n';
  1713.         }
  1714.  
  1715.         preamble += "\\makeatother\n\n";
  1716.  
  1717.         // Itemize bullet settings need to be last in case the user
  1718.         // defines their own bullets that use a package included
  1719.         // in the user-defined preamble -- ARRae
  1720.         for (int i = 0; i < 4; ++i) {
  1721.             if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
  1722.                 preamble += "\\renewcommand\\labelitemi";
  1723.                 switch (i) {
  1724.                     // `i' is one less than the item to modify
  1725.                 case 0:
  1726.                     break;
  1727.                 case 1:
  1728.                     preamble += 'i';
  1729.                     break;
  1730.                 case 2:
  1731.                     preamble += "ii";
  1732.                     break;
  1733.                 case 3:
  1734.                     preamble += 'v';
  1735.                     break;
  1736.                 }
  1737.                 preamble += "[0]{" + params.user_defined_bullets[i].getText() + "}\n";
  1738.             }
  1739.         }
  1740.  
  1741.         for (int j = preamble.countChar('\n'); j-- ;) {
  1742.             texrow.newline();
  1743.         }
  1744.  
  1745.         // A bit faster than printing a char at a time I think.
  1746.         fwrite(preamble.c_str(), sizeof(char),
  1747.                preamble.length(), file);
  1748.  
  1749.         // make the body.
  1750.         LFile += "\\begin{document}\n\n";
  1751.         texrow.newline();
  1752.         texrow.newline();
  1753.     } // only_body
  1754.     lyxerr.debug("preamble finished, now the body.");
  1755.     
  1756.     bool was_title = false;
  1757.     bool already_title = false;
  1758.     LString ftnote;
  1759.     TexRow ft_texrow;
  1760.     int ftcount = 0;
  1761.  
  1762.     LyXParagraph *par = paragraph;
  1763.  
  1764.     // if only_body
  1765.     while (par) {
  1766.         if (par->IsDummy())
  1767.             lyxerr.debug("Error in MakeLateXFile.", Error::LATEX);
  1768.         LyXLayout * layout = lyxstyle.Style(params.textclass,
  1769.                             par->layout);
  1770.         
  1771.             if (layout->intitle) {
  1772.             if (already_title) {
  1773.                 lyxerr.print("Error in MakeLatexFile: You"
  1774.                          " should not mix title layouts"
  1775.                          " with normal ones.");
  1776.             } else
  1777.                 was_title = true;
  1778.             } else if (was_title && !already_title) {
  1779.             LFile += "\\maketitle\n";
  1780.             texrow.newline();
  1781.             already_title = true;
  1782.             was_title = false;            
  1783.         }
  1784.         if (layout->isEnvironment()
  1785.                     || par->pextra_type != PEXTRA_NONE) {
  1786.             par = par->TeXEnvironment(LFile, texrow,
  1787.                           ftnote, ft_texrow, ftcount);
  1788.         } else {
  1789.             // We are at depth 0 so we can just use
  1790.             // ordinary \footnote{} generation
  1791.             // flag this with ftcount
  1792.             ftcount = -1;
  1793.             par = par->TeXOnePar(LFile, texrow,
  1794.                          ftnote, ft_texrow, ftcount);
  1795.             ftcount = 0;
  1796.         }
  1797.  
  1798.         // Write out what we've generated...and reset LFile
  1799.         fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
  1800.         LFile.erase();
  1801.         if (ftcount) {
  1802.             if (ftcount > 1) {
  1803.                 LFile += "\\addtocounter{footnote}{-";
  1804.                 LFile += ftcount - 1;
  1805.                 LFile += '}';
  1806.                 fwrite(LFile.c_str(), sizeof(char),
  1807.                        LFile.length(), file);
  1808.                        LFile.erase();
  1809.             }
  1810.             fwrite(ftnote.c_str(), sizeof(char),
  1811.                    ftnote.length(), file);
  1812.             texrow += ft_texrow;
  1813.             ftnote.erase();
  1814.             ft_texrow.reset();
  1815.             ftcount = 0;
  1816.         }
  1817.     }
  1818.  
  1819.     if (!only_body) {
  1820.         LFile += "\\end{document}\n";
  1821.         texrow.newline();
  1822.     
  1823.         lyxerr.debug("makeLaTeXFile...done", Error::LATEX);
  1824.     } else {
  1825.         lyxerr.debug("LaTeXFile for inclusion made.", Error::LATEX);
  1826.     }
  1827.  
  1828.     // Just to be sure. (Asger)
  1829.     texrow.newline();
  1830.  
  1831.     // Write out what we've generated...and reset LFile
  1832.     fwrite(LFile.c_str(), sizeof(char), LFile.length(), file);
  1833.     LFile.erase();
  1834.  
  1835.     if (file.close()) {
  1836.         WriteFSAlert(_("Error! Could not close file properly:"), filename);
  1837.     }
  1838.     lyxerr.debug("Finished making latex file.");
  1839. }
  1840.  
  1841.  
  1842. /* Temporary. Sorry. */
  1843. // Why isn't these in class Buffer? (even if they are temporary?)
  1844. static int depth;              /* paragraph depth */
  1845. static int enum_flags[10];     /* enum/itemize status */
  1846. static int desc_on;            /* description mode on/off */
  1847. // not true desc_on has more values than on/off
  1848. static bool verb_on;            /* verbatim mode on/off */
  1849. //static bool is_quote;           /* quote mode on/off */
  1850.  
  1851. void Buffer::linuxDocInitVars()
  1852. {
  1853.     depth = -1;
  1854.     enum_flags[0] = LINUXDOC_NONE;
  1855.     desc_on = 0;
  1856.     //is_quote = false;
  1857. }
  1858.  
  1859. void Buffer::linuxDocHandleFootnote(LyXParagraph* &par)
  1860. {
  1861.     while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
  1862.         /* no footnote support yet */
  1863.         par = par->next;
  1864.     }
  1865. }
  1866.  
  1867. void Buffer::linuxDocStartPar(FILE *file, LyXParagraph* &par)
  1868.     /* before article body : limited tag set */
  1869. {
  1870.     int     error = 0;                /* error flag */
  1871.     LString    error_message;        /* error message */
  1872.     LyXFont font;                     /* font information */
  1873.         static int oldtag = -1;
  1874.  
  1875.     if (!par) return;
  1876.     if (par->IsDummy()){
  1877.         error = 1;
  1878.         lyxerr.debug("Error in LinuxDocStartPar");
  1879.     }
  1880.     par->AutoDeleteInsets();
  1881.  
  1882.     int tag = LinuxDocTag(lyxstyle.NameOfLayout(params.textclass,
  1883.                             par->GetLayout()));
  1884.  
  1885.     LyXLayout *style=lyxstyle.Style(GetCurrentTextClass(), par->layout);
  1886.  
  1887.     // special handling for <toc> tag (\tableofcontents TeX macro)
  1888.     if (par->GetChar(0) == LYX_META_INSET) {
  1889.         Inset *inset = par->GetInset(0);
  1890.         char   lyx_code = inset->LyxCode();
  1891.         switch (lyx_code) {
  1892.         case Inset::TOC_CODE:
  1893.             fprintf(file, "\n<toc>");
  1894.             error = 1;     // fake : no futher processing required
  1895.             break;
  1896.         case Inset::HTMLURL_CODE: // Needed only to get <author> in sgml-file...
  1897.             if (tag == LINUXDOC_AUTHOR) {
  1898.                 if (oldtag != tag)
  1899.                     fprintf(file, "\n<%s>",
  1900.                         style->latexname.c_str());
  1901. //                else fprintf(file, "\n<and>");
  1902.                 else fprintf(file, "\n");
  1903.             }
  1904.             break;
  1905.         default:
  1906.             break;
  1907.         }
  1908.     } else {
  1909.         switch(tag) {
  1910.         case LINUXDOC_SECT:
  1911.             depth = 0;
  1912.         case LINUXDOC_TITLE:
  1913.         case LINUXDOC_AUTHOR:
  1914.         case LINUXDOC_DATE:
  1915.         case LINUXDOC_ABSTRACT:
  1916.             fprintf(file, "\n");
  1917.             if ((tag !=LINUXDOC_AUTHOR) || 
  1918.                 (oldtag != tag))  // two author-lines are not allowed in LinuxDoc...
  1919.                 fprintf(file, "<%s>", style->latexname.c_str());
  1920. //                else // (tag == LINUXDOC_AUTHOR) && (oldtag == tag)
  1921. //                                   fprintf(file, "<and>");
  1922.             break;
  1923.         default:
  1924.             error_message = _("Style ") + style->latexname + _(" not allowed before first Section."),
  1925.             LinuxDocError(par, 0, error_message);
  1926.             error = 1;
  1927.             break;
  1928.         }
  1929.     }
  1930.     if (!error) {
  1931.         SimpleLinuxDocOnePar(file, font, par, verb_on, desc_on);
  1932.         if (tag == LINUXDOC_SECT)
  1933.             fprintf(file, "\n<p>");
  1934.     }
  1935.     par = par->next;
  1936.     oldtag = tag;
  1937.     linuxDocHandleFootnote(par);
  1938. }
  1939.  
  1940.  
  1941. /* handle the layout constraints for a given paragraph */
  1942. void Buffer::linuxDocOnePar(FILE *file, LyXParagraph* &par) 
  1943. {
  1944.  
  1945.     LyXFont font;
  1946.     int i = 0;
  1947.  
  1948.     int error;                     /* error flag */
  1949.     LString error_message;        /* error message */
  1950.     int tag;                       /* number of the layout tag */
  1951.         static LString last_paragraph[10]; /* contains end of paragraph sign */
  1952.         LString special_tag_string, special_tag_close; /* special tags */
  1953.  
  1954.     /* standard initialisation */
  1955.     //is_quote = false;
  1956.     verb_on = 0;
  1957.     error = 0;
  1958.     LyXLayout *style=0;
  1959.     if (par) {
  1960.         if (par->IsDummy()){
  1961.             error = 1;
  1962.             lyxerr.debug("Error in LinuxDocOnePar");
  1963.         }
  1964.         par->AutoDeleteInsets();
  1965.         
  1966.         tag = LinuxDocTag(lyxstyle.NameOfLayout(params.textclass,
  1967.                             par->GetLayout()));
  1968.             style=lyxstyle.Style(GetCurrentTextClass(), par->layout);
  1969.     } else{
  1970.         if (depth == -1)
  1971.             return; /* No enumerate/itemize/descrip open */
  1972.         tag = -1; /* Undefined Token! */
  1973.     }
  1974.  
  1975.  
  1976.     /* handle enumerate, itemize and quote SGML tags closing */
  1977.     switch(enum_flags[depth]) {
  1978.     case LINUXDOC_ENUM:
  1979.     case LINUXDOC_ITEM:
  1980.         if (((tag != enum_flags[depth]) && (tag!=LINUXDOC_VERB) 
  1981.              && (tag!=LINUXDOC_CODE)) ||
  1982.             (par && (depth > par->depth))) {
  1983.             bool flag;
  1984.             do {
  1985.                                 flag = false;
  1986.                 if (!par || depth >=par->depth)
  1987.                     fprintf(file, "\n</%s>",
  1988.                         last_paragraph[depth].c_str());
  1989.                 if (depth == 0)
  1990.                     enum_flags[depth] = LINUXDOC_NONE;
  1991.                 if (par && (depth>par->depth)) 
  1992.                     { depth --; 
  1993.                     if ((tag != LINUXDOC_ENUM) &&
  1994.                         (tag != LINUXDOC_ITEM)   ) 
  1995.                         flag = true;
  1996.                     else flag = (depth > par->depth); 
  1997.                     }
  1998.             } while (flag);
  1999.         }
  2000.         break;
  2001.     default:
  2002.         if ((tag!=LINUXDOC_ITEM) && (tag!=LINUXDOC_ENUM) 
  2003.             && (par && (depth < par->depth))) {
  2004.             special_tag_string = "<quote>";
  2005.                         fprintf(file, "\n%s", special_tag_string.c_str());
  2006.             if (tag!=LINUXDOC_DESCR)
  2007.                 special_tag_close  = "</quote>";
  2008.         }
  2009.         break;
  2010.     }
  2011.  
  2012.     /* handle descriptions closing */
  2013.     if ((desc_on) &&
  2014.         ((tag != LINUXDOC_DESCR) || (!par) || (depth>par->depth))) {
  2015.                 int goal_depth = (par? par->depth : 0);
  2016.         while (depth>goal_depth) 
  2017.             { fprintf(file, "\n</descrip>");
  2018.             if (depth != 0) fprintf(file, "\n</quote>");
  2019.             --depth; 
  2020.             }
  2021.                 if (tag!=LINUXDOC_DESCR) fprintf(file, "\n</descrip>");
  2022.         if ((par) && (par->depth==0) && (tag!=LINUXDOC_DESCR))
  2023.             desc_on = 0;
  2024.     }
  2025.  
  2026.     if (!par) return; /* End of document! */
  2027.  
  2028.     /* write opening SGML tags */
  2029.     switch(tag) {
  2030.     case LINUXDOC_TITLE:
  2031.     case LINUXDOC_AUTHOR:
  2032.     case LINUXDOC_DATE:
  2033.     case LINUXDOC_ABSTRACT:
  2034.         error_message = LString(_("Style ")) + linuxdoc_styles[tag] + LString(_(" not allowed after first Section."));
  2035.         LinuxDocError(par ,i, error_message);
  2036.         error = 1;
  2037.         break;
  2038.     case LINUXDOC_PAR:
  2039.         if (special_tag_string.empty()) fprintf(file, "\n\n");
  2040.         else fprintf(file, "%s", special_tag_string.c_str());
  2041.         break;
  2042.     case LINUXDOC_VERB:
  2043.         font = par->getFont(0);
  2044.         verb_on = 1;
  2045.         /* special type handling for tscreen */
  2046.         if ((font.family() == LyXFont::TYPEWRITER_FAMILY)
  2047.             && (depth < par->depth)) {
  2048.             special_tag_string = "<tscreen>";
  2049.             special_tag_close  = "</tscreen>";
  2050.         }
  2051.         fprintf(file, "%s\n<verb>", special_tag_string.c_str());
  2052.         break;
  2053.     case LINUXDOC_CODE:
  2054.         fprintf(file, "%s\n<code>", special_tag_string.c_str());
  2055.         break;
  2056.     case LINUXDOC_SECT:
  2057.     case LINUXDOC_SECT1:
  2058.     case LINUXDOC_SECT2:
  2059.     case LINUXDOC_SECT3:
  2060.     case LINUXDOC_SECT4:
  2061.         if (depth!=0) {
  2062.             for (i=depth; i>=0; i--) {
  2063.                 if (enum_flags[depth]!=LINUXDOC_NONE)
  2064.                     fprintf(file, "\n</%s>",
  2065.                         linuxdoc_tags[enum_flags[depth]]);
  2066.                 enum_flags[i] = LINUXDOC_NONE;
  2067.             }
  2068.         }
  2069.         fprintf(file, "%s", special_tag_string.c_str());
  2070.         fprintf(file, "\n<%s>", style->latexname.c_str());
  2071.         break;
  2072.     case LINUXDOC_ENUM:
  2073.     case LINUXDOC_ITEM:
  2074.         if (depth < par->depth) {
  2075.             depth = par->depth;
  2076.             enum_flags[depth] = LINUXDOC_NONE;
  2077.         }
  2078.         if (enum_flags[depth] != tag) {
  2079.             last_paragraph[depth]= style->latexname;
  2080.             fprintf(file, "\n<%s>", last_paragraph[depth].c_str());
  2081.             enum_flags[depth] = tag;
  2082.         }
  2083.         fprintf(file, "\n<item>");
  2084.         depth = par->depth;
  2085.         break;
  2086.     case LINUXDOC_DESCR:
  2087.         if (!desc_on || depth<par->depth) {
  2088.             depth=par->depth;
  2089.             enum_flags[depth] = LINUXDOC_DESCR;
  2090.             fprintf(file, "\n<%s>", style->latexname.c_str());
  2091.         }
  2092.                 else if (depth>par->depth) {
  2093.             fprintf(file, "\n<%s>",
  2094.                 style->latexname.c_str());
  2095.             depth = par->depth;
  2096.         }
  2097.         fprintf(file, "\n<tag>");
  2098.         desc_on = 1;
  2099.         break;
  2100.     default:
  2101.         fprintf(file, "\n<%s>", style->latexname.c_str());
  2102.         break;
  2103.     } // switch(tag)
  2104.  
  2105.     if (!error) {
  2106.         SimpleLinuxDocOnePar(file, font, par, verb_on, desc_on);
  2107.     
  2108.         /* write closing SGML tags */
  2109.         switch(tag) {
  2110.         case LINUXDOC_ENUM:
  2111.         case LINUXDOC_ITEM:
  2112.         case LINUXDOC_DESCR:
  2113.         case LINUXDOC_PAR:
  2114.         case LINUXDOC_DATE:
  2115.         case LINUXDOC_AUTHOR:
  2116.         case LINUXDOC_TITLE:
  2117.             break;
  2118.         case LINUXDOC_SECT:
  2119.         case LINUXDOC_SECT1:
  2120.         case LINUXDOC_SECT2:
  2121.         case LINUXDOC_SECT3:
  2122.         case LINUXDOC_SECT4:
  2123.             fprintf(file, "\n<p>");
  2124.             break;
  2125.         default:
  2126.             fprintf(file, "\n</%s>", style->latexname.c_str());
  2127.             break;
  2128.         }
  2129.                 if (!special_tag_close.empty())
  2130.             fprintf(file, "%s", special_tag_close.c_str());
  2131.     }
  2132.  
  2133.     depth = par->depth;
  2134.     par = par->next;
  2135.  
  2136.     linuxDocHandleFootnote(par);
  2137. }
  2138.  
  2139.  
  2140. void Buffer::makeLinuxDocFile(LString const & filename, int column)
  2141. {
  2142.     LyXParagraph *par = paragraph;
  2143.     //LyXParagraph *prevpar = par;
  2144.  
  2145.     FilePtr file(filename, FilePtr::write);
  2146.     tex_code_break_column = column; 
  2147.  
  2148.     if (!file()) {
  2149.         WriteAlert(_("LYX_ERROR:"), _("Cannot write file"), filename);
  2150.         return;
  2151.     }
  2152.    
  2153.     //ResetTexRow();
  2154.     texrow.reset();
  2155.  
  2156.         LString userName(getUserName());
  2157.     fprintf(file,
  2158.         "<!-- LinuxDoc file was created by LyX 0.12 (C) 1995-1998 ");
  2159.     fprintf(file, "by <%s> %s -->\n", userName.c_str(), (char *)date());
  2160.     fprintf(file,
  2161.         "<!-- Export filter v0.6 by Pascal Andre/Bernhard Iselborn-->\n");
  2162.    
  2163.     if (params.preamble.empty()) {
  2164.         fprintf(file, "\n<!doctype linuxdoc system>\n\n");
  2165.     }
  2166.     else {
  2167.         fprintf(file, "\n<!doctype linuxdoc system \n [ %s \n]>\n\n", 
  2168.             params.preamble.c_str() );
  2169.     }
  2170.     fprintf(file, "<article>\n");   
  2171.  
  2172.         linuxDocInitVars();
  2173.  
  2174.     while (par) {
  2175.         if (par->IsDummy()) {
  2176.             lyxerr.debug("Error in MakeLinuxDocFile.");
  2177.             par = par->next;
  2178.                 } else if (depth == -1)
  2179.                         linuxDocStartPar(file, par);
  2180.                 else
  2181.             linuxDocOnePar(file, par);
  2182.     }
  2183.    
  2184.     linuxDocOnePar(file, par);
  2185.     fprintf(file, "\n\n</article>\n");
  2186.  
  2187.     if (file.close()) {
  2188.         WriteFSAlert(_("Error! Could not close file properly:"),
  2189.                  filename);
  2190.     }
  2191. }
  2192.  
  2193.  
  2194. /* gets tag number from layout name */
  2195. int Buffer::LinuxDocTag(LString const & layout)
  2196. {
  2197.     int i;
  2198.  
  2199.     for (i=0; i<LINUXDOC_NONE; i++)
  2200.         if (linuxdoc_styles[i] == layout) return i;
  2201.  
  2202.     return LINUXDOC_NONE;
  2203. }
  2204.  
  2205.  
  2206. /* push a tag in a style stack */
  2207. void Buffer::push_tag(FILE *file, char const *tag,
  2208.               int& pos, char stack[5][3])
  2209. {
  2210.     int j;
  2211.  
  2212.     /* pop all previous tags */
  2213.     for (j=pos; j>=0; j--)
  2214.         fprintf(file, "</%s>", stack[j]); 
  2215.  
  2216.     /* add new tag */
  2217.     sprintf(stack[++pos], "%s", tag);
  2218.  
  2219.     /* push all tags */
  2220.     for (j=0; j<=pos; j++)
  2221.         fprintf(file, "<%s>", stack[j]);
  2222. }
  2223.  
  2224.  
  2225. // pop a tag from a style stack
  2226. void Buffer::pop_tag(FILE *file, char const * tag,
  2227.              int& pos, char stack[5][3])
  2228. {
  2229.     int j;
  2230.  
  2231.     // pop all tags till specified one
  2232.     for (j=pos; (j>=0) && (strcmp(stack[j], tag)); j--)
  2233.         fprintf(file, "</%s>", stack[j]);
  2234.  
  2235.     // closes the tag
  2236.     fprintf(file, "</%s>", tag);
  2237.  
  2238.     // push all tags, but the specified one
  2239.     for (j=j+1; j<=pos; j++) {
  2240.         fprintf(file, "<%s>", stack[j]);
  2241.         strcpy(stack[j-1], stack[j]);
  2242.     }
  2243.     pos --;
  2244. }
  2245.  
  2246.  
  2247. // gets next latex parameter
  2248. // note: the convert-flag was introduced for work-arounds of the
  2249. // SGML-tool backend. But it had not the desired effekt.
  2250. // So it's "for further usage" :-)
  2251. int Buffer::GetNextParameter(LyXParagraph *par, int pos, LString ¶m, bool convert)
  2252. {
  2253.     int i, flag;
  2254.     char c;
  2255.     Inset *inset;
  2256.  
  2257.     flag = 1;
  2258.         param.erase();
  2259.     for (i=pos+1; i<=par->last && flag; i++) {
  2260.         c = par->GetChar(i);
  2261.         if (c == LYX_META_INSET) {
  2262.             inset = par->GetInset(i);
  2263.             switch (inset->LyxCode()) {
  2264.             case Inset::QUOTE_CODE:
  2265.                 c='\"';
  2266.                 break;
  2267.             case Inset::SEPARATOR_CODE:
  2268.             case Inset::ENDING_CODE:
  2269.                 flag = 0;
  2270.                 break;
  2271.             case Inset::TOC_CODE:
  2272.                 LinuxDocError(par, i, _("Error : table of contents not allowed "
  2273.                             "in body.\n"));
  2274.                 break;
  2275.             case Inset::IGNORE_CODE:
  2276.                 // ignore
  2277.                 break;
  2278.             default:
  2279.                 LinuxDocError(par, i, _("Error : unhandled inset.\n"));
  2280.                 break;
  2281.             }
  2282.         }
  2283.         if (flag) {
  2284.             LString temp;
  2285.             if (convert) linuxDocConvertChar(c, temp);
  2286.             else         temp=c;
  2287.             param += temp;
  2288.         }
  2289.     }
  2290.  
  2291.     if (flag) {
  2292.         LinuxDocError(par, pos, _("Error : incomplete macro.\n"));
  2293.         return 0;
  2294.     }
  2295.     return i;
  2296. }
  2297.  
  2298. bool Buffer::removeAutoInsets()
  2299. {
  2300.     LyXParagraph *par = paragraph;
  2301.  
  2302.     LyXCursor cursor = text->cursor;
  2303.     LyXCursor tmpcursor = cursor;
  2304.     cursor.par = tmpcursor.par->ParFromPos(tmpcursor.pos);
  2305.     cursor.pos = tmpcursor.par->PositionInParFromPos(tmpcursor.pos);
  2306.  
  2307.     bool a = false;
  2308.     while (par) {
  2309.         if (par->AutoDeleteInsets()){
  2310.             a = true;
  2311.             if (par->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE){
  2312.                 /* this is possible now, since SetCursor takes
  2313.                    care about footnotes */
  2314.                 text->SetCursorIntern(par, 0);
  2315.                 text->RedoParagraphs(text->cursor, text->cursor.par->Next());
  2316.                 text->FullRebreak();
  2317.             }
  2318.         }
  2319.         par = par->next;
  2320.     }
  2321.     /* avoid forbidden cursor positions caused by error removing */ 
  2322.     if (cursor.pos > cursor.par->Last())
  2323.         cursor.pos = cursor.par->Last();
  2324.     text->SetCursorIntern(cursor.par, cursor.pos);
  2325.  
  2326.     return a;
  2327. }
  2328.  
  2329.  
  2330. int Buffer::runLaTeX()
  2331. {
  2332.     if (!text) return 0;
  2333.  
  2334.     ProhibitInput();
  2335.  
  2336.     // get LaTeX-Filename
  2337.     LString name = SpaceLess(ChangeExtension (filename, ".tex", true));
  2338.  
  2339.     LString path = OnlyPath(filename);
  2340.  
  2341.     LString org_path = path;
  2342.     if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
  2343.         path = tmppath;     
  2344.     }
  2345.  
  2346.     //PathPush(path); // path to LaTeX file
  2347.     Path p(path);
  2348.     users->getOwner()->getMiniBuffer()->Set(_("Running LaTeX..."));   
  2349.  
  2350.     // Remove all error insets
  2351.     bool a = removeAutoInsets();
  2352.  
  2353.     // generate the LaTeX file if necessary
  2354.     if (!isDviClean() || a) {
  2355.         makeLaTeXFile(name, org_path, false);
  2356.         markDviDirty();
  2357.     }
  2358.  
  2359.     TeXErrors terr;
  2360.     LaTeX latex(lyxrc->latex_command, name, filepath);
  2361.     int res = latex.run(terr,users->getOwner()->getMiniBuffer()); // running latex
  2362.  
  2363.     // check return value from latex.run().
  2364.     if ((res & LaTeX::NO_LOGFILE)) {
  2365.         WriteAlert(_("LaTeX did not work!"),
  2366.                _("Missing log file:"), name);
  2367.     } else if ((res & LaTeX::ERRORS)) {
  2368.         users->getOwner()->getMiniBuffer()->Set(_("Done"));
  2369.         // Insert all errors as errors boxes
  2370.         insertErrors(terr);
  2371.         
  2372.         // Dvi should also be kept dirty if the latex run
  2373.         // ends up with errors. However it should be possible
  2374.         // to view a dirty dvi too.
  2375.     } else {
  2376.         //no errors or any other things to think about so:
  2377.         users->getOwner()->getMiniBuffer()->Set(_("Done"));
  2378.         markDviClean();
  2379.     }
  2380.  
  2381.     // if we removed error insets before we ran LaTeX or if we inserted
  2382.     // error insets after we ran LaTeX this must be run:
  2383.     if (a || (res & LaTeX::ERRORS)){
  2384.         users->redraw();
  2385.         users->fitCursor();
  2386.         users->updateScrollbar();
  2387.     }
  2388.     AllowInput();
  2389.     //PathPop(); // path to LaTeX file
  2390.  
  2391.     return latex.getNumErrors();
  2392. }
  2393.  
  2394.  
  2395. // This should be enabled when the Chktex class is implemented. (Asger)
  2396. // chktex should be run with these flags disabled: 3, 22, 25, 30, 38(?)
  2397. // Other flags: -wall -v0 -x
  2398. int Buffer::runChktex()
  2399. {
  2400.     if (!text) return 0;
  2401.  
  2402.     ProhibitInput();
  2403.  
  2404.     // get LaTeX-Filename
  2405.     LString name = SpaceLess(ChangeExtension (filename, ".tex", true));
  2406.     LString path = OnlyPath(filename);
  2407.  
  2408.     LString org_path = path;
  2409.     if (lyxrc->use_tempdir || (IsDirWriteable(path) < 1)) {
  2410.         path = tmppath;     
  2411.     }
  2412.  
  2413.     //PathPush(path); // path to LaTeX file
  2414.     Path p(path);
  2415.     users->getOwner()->getMiniBuffer()->Set(_("Running chktex..."));
  2416.  
  2417.     // Remove all error insets
  2418.     bool a = removeAutoInsets();
  2419.  
  2420.     // Generate the LaTeX file if neccessary
  2421.     if (!isDviClean() || a) {
  2422.         makeLaTeXFile(name, org_path, false);
  2423.         markDviDirty();
  2424.     }
  2425.  
  2426.     TeXErrors terr;
  2427.     Chktex chktex(lyxrc->chktex_command, name, filepath);
  2428.     int res = chktex.run(terr); // run chktex
  2429.  
  2430.     if (res == -1) {
  2431.         WriteAlert(_("chktex did not work!"),
  2432.                _("Could not run with file:"), name);
  2433.     } else if (res > 0) {
  2434.         // Insert all errors as errors boxes
  2435.         insertErrors(terr);
  2436.     }
  2437.  
  2438.     // if we removed error insets before we ran chktex or if we inserted
  2439.     // error insets after we ran chktex, this must be run:
  2440.     if (a || res){
  2441.         users->redraw();
  2442.         users->fitCursor();
  2443.         users->updateScrollbar();
  2444.     }
  2445.     AllowInput();
  2446.     //PathPop(); // path to LaTeX file
  2447.  
  2448.     return res;
  2449. }
  2450.  
  2451.  
  2452. extern void AllFloats(char, char);
  2453.  
  2454.  
  2455. void Buffer::insertErrors(TeXErrors &terr)
  2456. {
  2457.     // Save the cursor position
  2458.     LyXCursor cursor = text->cursor;
  2459.  
  2460.     // Now traverse all the errors and insert them
  2461.     bool firsterror = true;
  2462.     bool more = true;
  2463.  
  2464.     // This is drastic, but it's the only fix, I could find. (Asger)
  2465.     AllFloats(1,0);
  2466.     AllFloats(1,1);
  2467.  
  2468.     while (more) {
  2469.         LString errortext;
  2470.         int errorrow = 0;
  2471.  
  2472.         if (firsterror) {
  2473.             more = terr.getFirstError(&errorrow, &errortext);
  2474.             firsterror = false;
  2475.         } else {
  2476.             more = terr.getNextError(&errorrow, &errortext);
  2477.         }
  2478.  
  2479.         if (!more)
  2480.             break;
  2481.  
  2482.         // Insert error string for row number
  2483.         int tmpid = -1; 
  2484.         int tmppos = -1;
  2485.  
  2486.         texrow.getIdFromRow(errorrow, tmpid, tmppos);
  2487.  
  2488.         LyXParagraph* texrowpar;
  2489.  
  2490.         if (tmpid == -1) {
  2491.             texrowpar = text->FirstParagraph();
  2492.             tmppos = 0;
  2493.         } else {
  2494.             texrowpar = text->GetParFromID(tmpid);
  2495.         }
  2496.  
  2497.         if (texrowpar == 0)
  2498.             continue;
  2499.  
  2500.         InsetError *new_inset = new InsetError(errortext);
  2501.  
  2502.         text->SetCursorIntern(texrowpar, tmppos);
  2503.         text->InsertInset(new_inset);
  2504.         text->FullRebreak();
  2505.     }
  2506.     // Restore the cursor position
  2507.     text->SetCursorIntern(cursor.par, cursor.pos);
  2508. }
  2509.  
  2510.  
  2511. /* handle internal paragraph parsing -- layout already processed */
  2512.  
  2513. // checks, if newcol chars should be put into this line
  2514. // writes newline, if necessary.
  2515. static
  2516. void linux_doc_line_break(FILE *file, unsigned int &colcount, const unsigned int newcol)
  2517. {
  2518.     colcount += newcol;
  2519.     if (colcount > lyxrc->ascii_linelen) {
  2520.         fprintf(file, "\n");
  2521.         colcount = newcol; // assume write after this call
  2522.     }
  2523. }
  2524.  
  2525.  
  2526. void Buffer::SimpleLinuxDocOnePar(FILE *file, LyXFont &font1, 
  2527.                   LyXParagraph *par, bool &verb_on, 
  2528.                   int &desc_on) 
  2529. {
  2530.     LyXFont font2;
  2531.     char c;
  2532.     Inset *inset;
  2533.     int main_body, j;
  2534.     LyXLayout * style = lyxstyle.Style(params.textclass, par->GetLayout());
  2535.  
  2536.     bool is_tt = false;               // typewriter font flag 
  2537.     bool is_bf = false;               // bold font flag 
  2538.     bool is_em = false;               // emphasis (italic) font flag 
  2539.     bool is_quote = false;            // quote (paragraph indenting) flag 
  2540.  
  2541.     int stack_num = -1;          // style stack position 
  2542.     char stack[5][3];             // style stack 
  2543.         unsigned int char_line_count = 5;     // Heuristic choice ;-) 
  2544.  
  2545.     if (style->labeltype != LABEL_MANUAL)
  2546.         main_body = 0;
  2547.     else
  2548.         main_body = par->BeginningOfMainBody();
  2549.  
  2550.     /* gets paragraph main font */
  2551.     if (main_body > 0)
  2552.         font1 = style->labelfont;
  2553.     else
  2554.         font1 = style->font;
  2555.  
  2556.   
  2557.     /* parsing main loop */
  2558.     for (int i = 0; i < par->last; i++) {
  2559.  
  2560.         /* handle quote tag */
  2561.         if (i == main_body && !par->IsDummy()) {
  2562.             if (main_body > 0)
  2563.                 font1 = style->font;
  2564.             if ((!verb_on) && (par->align == LYX_ALIGN_RIGHT)) {
  2565.                 linux_doc_line_break(file, char_line_count, 7);
  2566.                 fprintf(file, "<quote>");
  2567.                 is_quote = true;
  2568.             }
  2569.         }
  2570.  
  2571.         font2 = par->getFont(i);
  2572.  
  2573.         /* handle <tt> tag */
  2574.         if (font1.family() != font2.family()) {
  2575.             if (verb_on)
  2576.                 LinuxDocError(par, 0,
  2577.                           "Error : TypeWriter font not"
  2578.                           " allowed in Verbatim.\n");
  2579.             else {
  2580.                 if (font2.family() == LyXFont::TYPEWRITER_FAMILY) {
  2581.                     push_tag(file, "tt", stack_num, stack);
  2582.                     is_tt = true;
  2583.                 } else if (is_tt) {
  2584.                     pop_tag(file, "tt", stack_num, stack);
  2585.                     is_tt = false;
  2586.                 }
  2587.             }
  2588.         }
  2589.  
  2590.         /* handle <bf> tag */
  2591.         if (font1.series() != font2.series()) {
  2592.             if (verb_on)
  2593.                 LinuxDocError(par, 0,
  2594.                           "Error : Bold font not allow"
  2595.                           " in Verbatim.\n");
  2596.             else {
  2597.                 if (font2.series() == LyXFont::BOLD_SERIES) {
  2598.                     push_tag(file, "bf", stack_num, stack);
  2599.                     is_bf = true;
  2600.                 }
  2601.                 else if (is_bf) {
  2602.                     pop_tag(file, "bf", stack_num, stack);
  2603.                     is_bf = false;
  2604.                 }
  2605.             }
  2606.         }
  2607.  
  2608.         /* handle <em> tag */
  2609.         if ((!verb_on) && (font1.shape() != font2.shape())) {
  2610.             if (verb_on)
  2611.                 LinuxDocError(par, 0,
  2612.                           "Error : Emphasis (italic font)"
  2613.                           " not allowed in Verbatim.\n");
  2614.             else {
  2615.                 if (font2.shape() == LyXFont::ITALIC_SHAPE) {
  2616.                     push_tag(file, "em", stack_num, stack);
  2617.                     is_em = true;
  2618.                 } else if (is_em) {
  2619.                     pop_tag(file, "em", stack_num, stack);
  2620.                     is_em = false;
  2621.                 }
  2622.             }
  2623.         }
  2624.       
  2625.         c = par->GetChar(i);
  2626.       
  2627.         if (font2.latex() == LyXFont::ON) {
  2628.             // "TeX"-Mode on ==> SGML-Mode on.
  2629.             if (c!='\0')
  2630.                 fprintf(file, "%c", c); // see LaTeX-Generation...
  2631.             char_line_count++;
  2632.         } else if (c == LYX_META_INSET) {
  2633.             inset = par->GetInset(i);
  2634.             switch (inset->LyxCode()) {
  2635.             case Inset::TOC_CODE:
  2636.                 LinuxDocError(par, i,
  2637.                           "Error: table of contents not"
  2638.                           " allowed in body.\n");
  2639.                 break;
  2640.             case Inset::QUOTE_CODE:
  2641.                 fprintf(file, "\"");
  2642.                 char_line_count++; char_line_count++;
  2643.                 break;
  2644.             case Inset::MARK_CODE:
  2645.             {
  2646.                 int j;
  2647.                 LString label;
  2648.  
  2649.                                
  2650.                 if ((j = GetNextParameter(par, i, label, true))) {
  2651.                     i = j; 
  2652.                         linux_doc_line_break(file,
  2653.                                  char_line_count,
  2654.                                  13+label.length());
  2655.                     fprintf(file,
  2656.                         "<label id=\"%s\">",
  2657.                         label.c_str());
  2658.                 }
  2659.                 i++;
  2660.             }
  2661.             break;
  2662.             case Inset::LABEL_CODE:
  2663.             {
  2664.                                 const char *out =
  2665.                     ((InsetLabel*) inset)->getLabel(1).c_str();
  2666.                 linux_doc_line_break(file, char_line_count, 13+strlen(out));
  2667.                 fprintf(file, "<label id=\"%s\">", out);
  2668.             }
  2669.             break;
  2670.             case Inset::REF_CODE:
  2671.             {
  2672.                 int j;
  2673.                 LString label, name;
  2674.  
  2675.                 // idea: If we have a LaTeX-reference,
  2676.                 //       then the name of the label is
  2677.                 //       If it's a SGML-version, then
  2678.                 //       we have two positional parameters
  2679.                 //       We got errors, if the names are
  2680.                 //       empty!
  2681.                 label = ((InsetCommand*)inset)->getContents();
  2682.                 if (label.empty()) {
  2683.                     if ((j = GetNextParameter(par, i, label, true)) && 
  2684.                             (j = GetNextParameter(par, j-1, name, true))) {
  2685.                         linux_doc_line_break(file, char_line_count, 
  2686.                                  20+label.length()+name.length());
  2687.                         i = j;
  2688.                     }
  2689.                     if (j == 0)
  2690.                     { // We got an error inset. We have to skip it...
  2691.                         i++;
  2692.                     }
  2693.                 }
  2694.                 else name = label;
  2695.                 if (!name.empty())    
  2696.                 {// name is empty implies, that we got
  2697.                  // an error above. So we can't write
  2698.                  // anything to the file
  2699.                     fprintf(file,
  2700.                         "<ref id=\"%s\" name=\"%s\">",
  2701.                         label.c_str(), name.c_str());
  2702.                 }
  2703.             }
  2704.             break;
  2705.             case Inset::URL_CODE:
  2706.             {
  2707.                 int j;
  2708.                 LString url, name;
  2709.  
  2710.                 if ((j = GetNextParameter(par, i, url, true)) && 
  2711.                     (j = GetNextParameter(par, j-1, name, true))) {
  2712.                     linux_doc_line_break(file, char_line_count, 
  2713.                                  20+url.length()+name.length());
  2714.                     i = j;
  2715.                     fprintf(file,
  2716.                         "<url url=\"%s\" name=\"%s\">",
  2717.                         url.c_str(), name.c_str());
  2718.                 }
  2719.             }
  2720.             break;
  2721.             case Inset::HTMLURL_CODE:
  2722.             {
  2723.                 int j;
  2724.                 LString url, name;
  2725.  
  2726.                 if ((j = GetNextParameter(par, i, url, true)) && 
  2727.                     (j = GetNextParameter(par, j-1, name, true))) {
  2728.                     linux_doc_line_break(file, char_line_count, 
  2729.                                  24+url.length()+name.length());
  2730.                     i = j;
  2731.                     fprintf(file, "<htmlurl url=\"%s\" name=\"%s\">", url.c_str(), name.c_str());
  2732.                 }
  2733.             }
  2734.             break;
  2735.             case Inset::IGNORE_CODE:
  2736.                 /* ignore */ 
  2737.                 break;
  2738.             default:
  2739.                 LinuxDocError(par, i, 
  2740.                           "Error : unhandled inset.\n");
  2741.                 i++;
  2742.                 break;
  2743.             }
  2744.         }
  2745.         else {
  2746.             LString sgml_string;
  2747.             if (linuxDocConvertChar(c, sgml_string) 
  2748.                 && !style->free_spacing) { // in freespacing
  2749.                                      // mode, spaces are
  2750.                                      // non-breaking characters
  2751.                 // char is ' '
  2752.                 if (desc_on == 1) {
  2753.                     char_line_count++;
  2754.                     linux_doc_line_break(file, char_line_count, 6);
  2755.                     fprintf(file, "</tag>");
  2756.                     desc_on = 2;
  2757.                 }
  2758.                 else  {
  2759.                     linux_doc_line_break(file, char_line_count, 1);
  2760.                     fprintf(file, "%c", c);
  2761.                 }
  2762.             }
  2763.             else {
  2764.                 fprintf(file, "%s", sgml_string.c_str());
  2765.                 char_line_count += sgml_string.length();
  2766.             }
  2767.         }
  2768.         font1 = font2;
  2769.     }
  2770.  
  2771.     /* needed if there is an optional argument but no contents */ 
  2772.     if (main_body > 0 && main_body == par->last) {
  2773.         font1 = style->font;
  2774.     }
  2775.  
  2776.     /* pop all defined Styles (non verbatim) */
  2777.     if (!verb_on) 
  2778.         for (j=stack_num; j>=0; j--) {
  2779.             linux_doc_line_break(file, 
  2780.                          char_line_count, 
  2781.                          3+strlen(stack[j]));
  2782.             fprintf(file, "</%s>", stack[j]);
  2783.         }
  2784.  
  2785.     /* closes quote tag if necessary */
  2786.     if (is_quote) {
  2787.         linux_doc_line_break(file, char_line_count, 8);
  2788.         fprintf(file, "</quote>");
  2789.     }
  2790.  
  2791.     /* resets description flag correctly */
  2792.     if (desc_on == 2) {
  2793.         desc_on = 1;
  2794.     } else if (desc_on == 1) { 
  2795.         /* <tag> not closed... */
  2796.         linux_doc_line_break(file, char_line_count, 6);
  2797.         fprintf(file, "</tag>\n");
  2798.     }
  2799. }
  2800.  
  2801.  
  2802. bool Buffer::linuxDocConvertChar(char c, LString &sgml_string)
  2803. {
  2804.     bool retval = false;
  2805.     switch (c) {
  2806.     case LYX_META_HFILL:
  2807.                 sgml_string.erase();
  2808.         break;
  2809.     case LYX_META_PROTECTED_SEPARATOR: 
  2810.         sgml_string = ' ';
  2811.         break;
  2812.     case LYX_META_NEWLINE:
  2813.         sgml_string = '\n';
  2814.         break;
  2815.     case '&': 
  2816.         sgml_string = "&";
  2817.         break;
  2818.     case '<': 
  2819.         sgml_string = "<"; 
  2820.         break;
  2821.     case '>':
  2822.         sgml_string = ">"; 
  2823.         break;
  2824.     case '$': 
  2825.         sgml_string = "$"; 
  2826.         break;
  2827.     case '#': 
  2828.         sgml_string = "#";
  2829.         break;
  2830.     case '%': 
  2831.         sgml_string = "%";
  2832.         break;
  2833.     case '[': 
  2834.         sgml_string = "[";
  2835.         break;
  2836.     case ']': 
  2837.         sgml_string = "]";
  2838.         break;
  2839.     case '{': 
  2840.         sgml_string = "{";
  2841.         break;
  2842.     case '}': 
  2843.         sgml_string = "}";
  2844.         break;
  2845.     case '~': 
  2846.         sgml_string = "˜";
  2847.         break;
  2848.     case '\"': 
  2849.         /* should work says the doc, but ... fprintf(file, "&dquote;"); */
  2850.         sgml_string = "\"";
  2851.         break;
  2852.     case ' ':
  2853.         retval = true;
  2854.                 sgml_string = ' ';
  2855.         break;
  2856.     case '\0': /* Ignore :-) */
  2857.                 sgml_string.erase();
  2858.         break;
  2859.     default:
  2860.         sgml_string = c;
  2861.         break;
  2862.     }
  2863.     return retval;
  2864. }
  2865.  
  2866.  
  2867. /* print an error message */
  2868. void Buffer::LinuxDocError(LyXParagraph *par, int pos,
  2869.                LString const &message) 
  2870. {
  2871.     InsetError *new_inset;
  2872.  
  2873.     /* insert an error marker in text */
  2874.     new_inset = new InsetError(message);
  2875.     par->InsertChar(pos, LYX_META_INSET);
  2876.     par->InsertInset(pos, new_inset);
  2877. }
  2878.  
  2879.  
  2880. void Buffer::RoffAsciiTable(FILE *file, LyXParagraph *par)
  2881. {
  2882.     LyXFont
  2883.         font1 =  LyXFont(LyXFont::ALL_INHERIT),
  2884.         font2;
  2885.     Inset
  2886.         *inset;
  2887.     int
  2888.         i,j,
  2889.         cell = 0;
  2890.     char
  2891.         c;
  2892.     LString
  2893.         fname1,
  2894.         fname2;
  2895.     FILE
  2896.         *fp,*fp2;
  2897.     
  2898.     fname1 = TmpFileName(LString(),"RAT1");
  2899.     fname2 = TmpFileName(LString(),"RAT2");
  2900.     if (!(fp=fopen(fname1.c_str(),"w"))) {
  2901.         WriteAlert(_("LYX_ERROR:"),
  2902.                _("Cannot open temporary file:"), fname1);
  2903.         return;
  2904.     }
  2905.     par->table->RoffEndOfCell(fp, -1);
  2906.     for (i = 0; i < par->last; i++) {
  2907.         c = par->GetChar(i);
  2908.         if (par->table->IsContRow(cell)) {
  2909.             if (c == LYX_META_NEWLINE)
  2910.                 cell++;
  2911.             continue;
  2912.         }
  2913.         font2 = par->GetFontSettings(i);
  2914.         if (font1.latex() != font2.latex()) {
  2915.             if (font2.latex() != LyXFont::OFF)
  2916.                 continue;
  2917.         }
  2918.         switch (c) {
  2919.         case LYX_META_INSET:
  2920.             if ((inset = par->GetInset(i))) {
  2921.                 if (!(fp2=fopen(fname2.c_str(),"w+"))) {
  2922.                     WriteAlert(_("LYX_ERROR:"),
  2923.                            _("Cannot open temporary file:"), fname2);
  2924.                     fclose(fp);
  2925.                     remove(fname1.c_str());
  2926.                     return;
  2927.                 }
  2928.                 inset->Latex(fp2,-1);
  2929.                 rewind(fp2);
  2930.                 c = fgetc(fp2);
  2931.                 while(!feof(fp2)) {
  2932.                     if (c == '\\')
  2933.                         fprintf(fp,"\\\\");
  2934.                     else
  2935.                         fputc(c,fp);
  2936.                     c = fgetc(fp2);
  2937.                 }
  2938.                 fclose(fp2);
  2939.             }
  2940.             break;
  2941.         case LYX_META_NEWLINE:
  2942.             if (par->table->CellHasContRow(cell)>=0)
  2943.                 par->RoffContTableRows(fp, i+1,cell);
  2944.             par->table->RoffEndOfCell(fp, cell);
  2945.             cell++;
  2946.             break;
  2947.         case LYX_META_HFILL: 
  2948.             break;
  2949.         case LYX_META_PROTECTED_SEPARATOR:
  2950.             break;
  2951.         case '\\': 
  2952.             fprintf(fp, "\\\\");
  2953.             break;
  2954.         default:
  2955.             if (c != '\0')
  2956.                 fprintf(fp, "%c", c);
  2957.             else if (c == '\0')
  2958.                 lyxerr.debug("RoffAsciiTable:"
  2959.                          " NULL char in structure.");
  2960.             break;
  2961.         }
  2962.     }
  2963.     par->table->RoffEndOfCell(fp, cell);
  2964.     fclose(fp);
  2965.     LString cmd = lyxrc->ascii_roff_command + " >" + fname2;
  2966.     cmd.subst("$$FName",fname1);
  2967.     Systemcalls one(Systemcalls::System, cmd);
  2968.     if (!(lyxerr.debugging())) {
  2969.         remove(fname1.c_str());
  2970.     }
  2971.     if (!(fp=fopen(fname2.c_str(),"r"))) {
  2972.         WriteFSAlert(_("Error! Can't open temporary file:"), fname2);
  2973.         return;
  2974.     }
  2975.     // now output the produced file
  2976.     fprintf(file, "\n\n");
  2977.     c = fgetc(fp);
  2978.     if (feof(fp))
  2979.         WriteAlert(_("Error!"),
  2980.                _("Error executing *roff command on table"));
  2981.     // overread leading blank lines
  2982.     while(!feof(fp) && (c == '\n'))
  2983.         c = fgetc(fp);
  2984.     while(!feof(fp)) {
  2985.         for(j=0; j<par->depth; j++)
  2986.             fprintf(file, "  ");
  2987.         while(!feof(fp) && (c != '\n')) {
  2988.             fputc(c,file);
  2989.             c = fgetc(fp);
  2990.         }
  2991.         fputc('\n',file);
  2992.         // overread trailing blank lines
  2993.         while(!feof(fp) && (c == '\n'))
  2994.             c = fgetc(fp);
  2995.     }
  2996.     fclose(fp);
  2997.     remove(fname2.c_str());
  2998. }
  2999.  
  3000.  
  3001. bool Buffer::isLinuxDoc()
  3002. {
  3003.     return lyxstyle.NameOfClass(params.textclass) == "linuxdoc";
  3004. }
  3005.  
  3006.  
  3007. void Buffer::update(signed char f)
  3008. {
  3009.     if (!users) return;
  3010.     
  3011.     users->getOwner()->updateLayoutChoice();
  3012.  
  3013.     if (!text->selection && f > -3)
  3014.         text->sel_cursor = text->cursor;
  3015.     
  3016.     FreeUpdateTimer();
  3017.     text->FullRebreak();
  3018.     users->update();
  3019.  
  3020.     if (f != 3 && f != -3) {
  3021.         users->fitCursor();
  3022.         users->updateScrollbar();
  3023.           }
  3024.  
  3025.     if (f==1 || f==-1) {
  3026.         if (isLyxClean()) {
  3027.             markDirty();
  3028.             users->getOwner()->getMiniBuffer()->setTimer(4);
  3029.         } else {
  3030.             markDirty();
  3031.         }
  3032.     }
  3033. }
  3034.  
  3035.  
  3036. void Buffer::validate(LaTeXFeatures &features)
  3037. {
  3038.     LyXParagraph *par = paragraph;
  3039.         LyXTextClass *tclass = lyxstyle.TextClass(params.textclass);
  3040.     
  3041.         // AMS Style is at document level
  3042.     
  3043.         features.amsstyle = (params.use_amsmath ||
  3044.                  tclass->latexname.prefixIs("ams"));
  3045.     
  3046.     while (par) {
  3047.         // We don't use "lyxerr.debug" because of speed. (Asger)
  3048.         if (lyxerr.debugging(Error::LATEX))
  3049.             lyxerr.print(LString("Paragraph: ") + long(par));
  3050.  
  3051.         // Now just follow the list of paragraphs and run
  3052.         // validate on each of them.
  3053.         par->validate(features);
  3054.  
  3055.         // and then the next paragraph
  3056.         par = par->next;
  3057.     }
  3058.  
  3059.     // the bullet shapes are buffer level not paragraph level
  3060.     // so they are tested here
  3061.     for (int i = 0; i < 4; ++i) {
  3062.         if (params.user_defined_bullets[i] != ITEMIZE_DEFAULTS[i]) {
  3063.             int font = params.user_defined_bullets[i].getFont();
  3064.             if (font == 0) {
  3065.                 int c = params.user_defined_bullets[i].getCharacter();
  3066.                 if (c == 16
  3067.                    || c == 17
  3068.                    || c == 25
  3069.                    || c == 26
  3070.                    || c == 31) {
  3071.                     features.latexsym = true;
  3072.                 }
  3073.             }
  3074.             if (font == 1) {
  3075.                 features.amssymb = true;
  3076.             }
  3077.             else if ((font >= 2 && font <=5)) {
  3078.                 features.pifont = true;
  3079.             }
  3080.         }
  3081.     }
  3082.     
  3083.     if (lyxerr.debugging(Error::LATEX)) {
  3084.         features.showStruct(params);
  3085.     }
  3086. }
  3087.  
  3088.  
  3089. void Buffer::setPaperStuff()
  3090. {
  3091.     char c1, c2;
  3092.  
  3093.     params.papersize = PAPER_DEFAULT;
  3094.     c1 = params.paperpackage;
  3095.     if (c1 == PACKAGE_NONE) {
  3096.         c2 = params.papersize2;
  3097.         if (c2 == VM_PAPER_USLETTER)
  3098.             params.papersize = PAPER_USLETTER;
  3099.         else if (c2 == VM_PAPER_USLEGAL)
  3100.             params.papersize = PAPER_LEGALPAPER;
  3101.         else if (c2 == VM_PAPER_USEXECUTIVE)
  3102.             params.papersize = PAPER_EXECUTIVEPAPER;
  3103.         else if (c2 == VM_PAPER_A3)
  3104.             params.papersize = PAPER_A3PAPER;
  3105.         else if (c2 == VM_PAPER_A4)
  3106.             params.papersize = PAPER_A4PAPER;
  3107.         else if (c2 == VM_PAPER_A5)
  3108.             params.papersize = PAPER_A5PAPER;
  3109.         else if ((c2 == VM_PAPER_B3) || (c2 == VM_PAPER_B4) ||
  3110.              (c2 == VM_PAPER_B5))
  3111.             params.papersize = PAPER_B5PAPER;
  3112.     } else if ((c1 == PACKAGE_A4) || (c1 == PACKAGE_A4WIDE) ||
  3113.            (c1 == PACKAGE_WIDEMARGINSA4))
  3114.         params.papersize = PAPER_A4PAPER;
  3115. }
  3116.  
  3117.  
  3118. void Buffer::setOldPaperStuff()
  3119. {
  3120.     char c;
  3121.  
  3122.     c = params.papersize = params.papersize2;
  3123.     params.papersize2 = VM_PAPER_DEFAULT;
  3124.     params.paperpackage = PACKAGE_NONE;
  3125.     if (c == OLD_PAPER_A4PAPER)
  3126.         params.papersize2 = VM_PAPER_A4;
  3127.     else if (c == OLD_PAPER_A4)
  3128.         params.paperpackage = PACKAGE_A4;
  3129.     else if (c == OLD_PAPER_A4WIDE)
  3130.         params.paperpackage = PACKAGE_A4WIDE;
  3131.     else if (c == OLD_PAPER_WIDEMARGINSA4)
  3132.         params.paperpackage = PACKAGE_WIDEMARGINSA4;
  3133.     else if (c == OLD_PAPER_USLETTER)
  3134.         params.papersize2 = VM_PAPER_USLETTER;
  3135.     else if (c == OLD_PAPER_A5PAPER)
  3136.         params.papersize2 = VM_PAPER_A5;
  3137.     else if (c == OLD_PAPER_B5PAPER)
  3138.         params.papersize2 = VM_PAPER_B5;
  3139.     else if (c == OLD_PAPER_EXECUTIVEPAPER)
  3140.         params.papersize2 = VM_PAPER_USEXECUTIVE;
  3141.     else if (c == OLD_PAPER_LEGALPAPER)
  3142.         params.papersize2 = VM_PAPER_USLEGAL;
  3143.     setPaperStuff();
  3144. }
  3145.  
  3146.  
  3147. void Buffer::insertInset(Inset *inset, LString const &lout,
  3148.              bool no_table)
  3149. {
  3150.     // check for table/list in tables
  3151.     if (no_table && text->cursor.par->table){
  3152.         WriteAlert(_("Impossible Operation!"),
  3153.                _("Cannot insert table/list in table."),
  3154.                _("Sorry."));
  3155.         return;
  3156.     }
  3157.     // not quite sure if we want this...
  3158.     text->SetCursorParUndo();
  3159.     text->FreezeUndo();
  3160.     
  3161.     BeforeChange();
  3162.     if (!lout.empty()) {
  3163.         update(-2);
  3164.         text->BreakParagraph();
  3165.         update(-1);
  3166.         
  3167.         if (text->cursor.par->Last()) {
  3168.             text->CursorLeft();
  3169.             
  3170.             text->BreakParagraph();
  3171.             update(-1);
  3172.         }
  3173.  
  3174.         int lay = lyxstyle.NumberOfLayout(params.textclass, lout);
  3175.         if (lay == -1) // layout not found
  3176.             // use default layout "Standard" (0)
  3177.             lay = 0;
  3178.         
  3179.         text->SetLayout(lay);
  3180.         
  3181.         text->SetParagraph(0, 0,
  3182.                    0, 0,
  3183.                    VSpace::NONE, VSpace::NONE,
  3184.                    LYX_ALIGN_LAYOUT, 
  3185.                    LString(),
  3186.                    0);
  3187.         update(-1);
  3188.         
  3189.         text->current_font.setLatex(LyXFont::OFF);
  3190.     }
  3191.     
  3192.     text->InsertInset(inset);
  3193.     update(-1);
  3194.  
  3195. // Commenting these two lines fixes the problem with new display inset
  3196. // inside a paragraph, not sure why. (ale 971117)
  3197. //    if (inset->Display())
  3198. //        text->CursorRight();
  3199.     
  3200.     text->UnFreezeUndo();    
  3201. }
  3202.  
  3203.  
  3204. // Open and lock an updatable inset
  3205. void Buffer::open_new_inset(UpdatableInset* new_inset)
  3206. {
  3207.     BeforeChange();
  3208.     text->FinishUndo();
  3209.     insertInset(new_inset);
  3210.     text->CursorLeft();
  3211.     update(1);
  3212.         new_inset->Edit(0,0);
  3213. }
  3214.  
  3215.  
  3216. /* This function should be in Buffer because it's a buffer's property (ale) */
  3217. LString Buffer::getIncludeonlyList(char delim)
  3218. {
  3219.     LString list;
  3220.     LyXParagraph *par = paragraph;
  3221.     int pos;
  3222.     Inset* inset;
  3223.     while (par){
  3224.         pos = -1;
  3225.         while ((inset = par->ReturnNextInsetPointer(pos))){
  3226.             if (inset->LyxCode()==Inset::INCLUDE_CODE) {
  3227.                 InsetInclude *insetinc = (InsetInclude*)inset;
  3228.                 if (insetinc->isInclude() 
  3229.                     && insetinc->isNoLoad()) {
  3230.                     if (!list.empty())
  3231.                         list += delim;
  3232.                     list += ChangeExtension(insetinc->getContents(), LString(), true);
  3233.                 }
  3234.             }
  3235.             pos++;
  3236.         } 
  3237.         par = par->next;
  3238.     }
  3239.     lyxerr.print(LString("Includeonly(") + list + ')');
  3240.     return list;
  3241. }
  3242.  
  3243.  
  3244. /* This is also a buffer property (ale) */ 
  3245. LString Buffer::getReferenceList(char delim)
  3246. {
  3247.     LyXParagraph *par = paragraph;
  3248.     int pos;
  3249.     Inset* inset;
  3250.         LString list;
  3251.     while (par){
  3252.         pos = -1;
  3253.         while ((inset = par->ReturnNextInsetPointer(pos))){     
  3254.             for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
  3255.                 if (!list.empty())
  3256.                     list += delim;
  3257.                 list += inset->getLabel(i);
  3258.             }
  3259.             pos++;
  3260.         } 
  3261.         par = par->next;
  3262.     }
  3263.     lyxerr.debug(LString("References(") + list + LString(")"));
  3264.     return list;
  3265. }
  3266.  
  3267.  
  3268. /* This is also a buffer property (ale) */
  3269. // Not so sure about that. a goto Label function can not be buffer local, just
  3270. // think how this will work in a multiwindo/buffer environment, all the
  3271. // cursors in all the views showing this buffer will move. (Lgb)
  3272. // OK, then no cursor action should be allowed in buffer. (ale)
  3273. bool Buffer::gotoLabel(const LString &label)
  3274. {
  3275.         LyXParagraph *par = paragraph;
  3276.         int pos;
  3277.         Inset* inset;
  3278.     LString list;
  3279.         while (par) {
  3280.                 pos = -1;
  3281.                 while ((inset = par->ReturnNextInsetPointer(pos))){     
  3282.                         for (int i = 0; i < inset->GetNumberOfLabels(); i++) {
  3283.                 if (label==inset->getLabel(i)) {
  3284.                     BeforeChange();
  3285.                     text->SetCursor(par, pos);
  3286.                     text->sel_cursor = text->cursor;
  3287.                     update(0);
  3288.                     return true;
  3289.                 }
  3290.             }
  3291.                         pos++;
  3292.                 } 
  3293.                 par = par->next;
  3294.     }
  3295.     return false;
  3296. }
  3297.  
  3298.  
  3299. bool Buffer::isDepClean(LString const & name) const
  3300. {
  3301.     DEPCLEAN* item = dep_clean;
  3302.     while (item && item->master != name)
  3303.         item = item->next;
  3304.     if (!item) return true;
  3305.     return item->clean;
  3306. }
  3307.  
  3308.  
  3309. void Buffer::markDepClean(LString const & name)
  3310. {
  3311.     if (!dep_clean) {
  3312.         dep_clean = new DEPCLEAN;
  3313.         dep_clean->clean = true;
  3314.         dep_clean->master = name;
  3315.         dep_clean->next = NULL;
  3316.     } else {
  3317.         DEPCLEAN* item = dep_clean;
  3318.         while (item && item->master != name)
  3319.             item = item->next;
  3320.         if (item) {
  3321.             item->clean = true;
  3322.         } else {
  3323.             item = new DEPCLEAN;
  3324.             item->clean = true;
  3325.             item->master = name;
  3326.             item->next = NULL;;
  3327.         }
  3328.     }
  3329.     //return false; // why use that in a void method??
  3330. }
  3331.