]> git.lyx.org Git - features.git/blob - src/paragraph.C
Initial revision
[features.git] / src / paragraph.C
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 *======================================================*/
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation "lyxparagraph.h"
15 #endif
16
17 #include "lyxparagraph.h"
18 #include "lyxrc.h"
19 #include "layout.h"
20 #include "tex-strings.h"
21 #include "bufferparams.h"
22 #include "FileInfo.h"
23 #include "error.h"
24 #include "LaTeXFeatures.h"
25 #include "insets/insetinclude.h"
26 #include "filetools.h"
27 #include "lyx_gui_misc.h"
28 #include "texrow.h"
29
30 //      $Id: paragraph.C,v 1.1 1999/09/27 18:44:38 larsbj Exp $ 
31
32 #if !defined(lint) && !defined(WITH_WARNINGS)
33 static char vcid[] = "$Id: paragraph.C,v 1.1 1999/09/27 18:44:38 larsbj Exp $";
34 #endif /* lint */
35
36 #define INITIAL_SIZE_PAR 10 /*Number of bytes in one paragraph*/
37 #define STEP_SIZE_PAR 10 /*Number of bytes added when reallocated*/
38
39 extern void addNewlineAndDepth(LString & file, int const depth); // Jug 990923
40 extern unsigned char GetCurrentTextClass(); // this should be fixed/removed
41 int tex_code_break_column = 72;  // needs non-zero initialization. set later.
42 // this is a bad idea, but how can LyXParagraph find its buffer to get
43 // parameters? (JMarc)
44 extern BufferView *current_view;
45 extern LyXRC *lyxrc;
46
47
48 // ale970405
49 extern LString bibitemWidthest();
50
51 /* this is a minibuffer */
52 static char minibuffer_char;
53 static LyXFont minibuffer_font;
54 static Inset *minibuffer_inset;
55
56
57 // Initialization of the counter for the paragraph id's,
58 // declared in lyxparagraph.h
59 unsigned int LyXParagraph::paragraph_id = 0;
60
61
62 LyXParagraph::LyXParagraph()
63 {
64         size = INITIAL_SIZE_PAR;
65         last = 0;
66         text = new char[size];
67         for (int i=0; i<10; i++) setCounter(i , 0);
68         appendix = false;
69         enumdepth = 0;
70         itemdepth = 0;
71         next = NULL;
72         previous = NULL;
73         fonttable = NULL;
74         insettable = NULL;
75         footnoteflag = LyXParagraph::NO_FOOTNOTE;
76
77         align = LYX_ALIGN_BLOCK;
78
79         /* table stuff -- begin*/ 
80         table = NULL;
81         /* table stuff -- end*/ 
82         id = paragraph_id++;
83         bibkey = NULL; // ale970302
84         Clear();
85 }
86
87
88 /* this konstruktor inserts the new paragraph in a list */ 
89 LyXParagraph::LyXParagraph(LyXParagraph *par)
90 {
91         size = INITIAL_SIZE_PAR;
92         last = 0;
93         text = new char[size];
94         for (int i=0; i<10; i++) setCounter(i, 0);
95         appendix = false;
96         enumdepth = 0;
97         itemdepth = 0;
98         next = par->next;
99         if (next)
100                 next->previous = this;
101         previous = par;
102         previous->next = this;
103         fonttable = NULL;
104         insettable = NULL;
105         footnoteflag = LyXParagraph::NO_FOOTNOTE;
106         footnotekind = LyXParagraph::FOOTNOTE;
107         
108         /* table stuff -- begin*/ 
109         table = NULL;
110         /* table stuff -- end*/ 
111         id = paragraph_id++;
112
113         bibkey = NULL; // ale970302        
114         // ale970302
115 //        fprintf(stderr, "new bib "); fflush(stderr);    
116 //        if (par->bibkey) {
117 //          bibkey = new InsetBibKey(par->bibkey);
118 //        }
119     
120         Clear();
121 }
122
123 /// Used by the spellchecker
124 bool LyXParagraph::IsLetter(int pos){
125         unsigned char c = GetChar(pos);
126         if (IsLetterChar(c))
127                 return true;
128         // '\0' is not a letter, allthough every string contains "" (below)
129         if( c == '\0')
130                 return false;
131         // We want to pass the ' and escape chars to ispell
132         LString extra = lyxrc->isp_esc_chars + '\'';
133         char ch[2];
134         ch[0] = c;
135         ch[1] = 0;
136         return extra.contains(ch);
137 }
138
139
140 void LyXParagraph::writeFile(FILE *file, BufferParams &params,
141                              char footflag, char dth)
142 {
143         LyXFont font1, font2;
144         Inset *inset;
145         int column = 0;
146         int h = 0;
147         char c = 0;
148
149         if (footnoteflag != LyXParagraph::NO_FOOTNOTE
150             || !previous
151             || previous->footnoteflag == LyXParagraph::NO_FOOTNOTE){
152                 
153                 /* The beginning or the end of a footnote environment? */ 
154                 if (footflag != footnoteflag) {
155                         footflag = footnoteflag;
156                         if (footflag) {
157                                 fprintf(file, "\n\\begin_float %s ", 
158                                         string_footnotekinds[footnotekind]);
159                         }
160                         else {
161                                 fprintf(file, "\n\\end_float ");
162                         }
163                 }
164
165                 /* The beginning or end of a deeper (i.e. nested) area? */
166                 if (dth != depth) {
167                         if (depth > dth) {
168                                 while (depth > dth) {
169                                         fprintf(file, "\n\\begin_deeper ");
170                                         dth++;
171                                 }
172                         }
173                         else {
174                                 while (depth < dth) {
175                                         fprintf(file, "\n\\end_deeper ");
176                                         dth--;
177                                 }
178                         }
179                 }
180
181                 /* First write the layout */ 
182                 fprintf(file, "\n\\layout %s\n",
183                         lyxstyle.NameOfLayout(params.textclass,layout).c_str());
184
185                 /* maybe some vertical spaces */ 
186                 if (added_space_top.kind() != VSpace::NONE)
187                         fprintf(file, "\\added_space_top %s ", 
188                                 added_space_top.asLyXCommand().c_str());
189                 if (added_space_bottom.kind() != VSpace::NONE)
190                         fprintf(file, "\\added_space_bottom %s ",
191                                 added_space_bottom.asLyXCommand().c_str());
192                         
193                 /* The labelwidth string used in lists */
194                 if (!labelwidthstring.empty())
195                         fprintf(file, "\\labelwidthstring %s\n",
196                                 labelwidthstring.c_str());
197
198                 /* Lines above or below? */
199                 if (line_top)
200                         fprintf(file, "\\line_top ");
201                 if (line_bottom)
202                         fprintf(file, "\\line_bottom ");
203
204                 /* Pagebreaks above or below? */
205                 if (pagebreak_top)
206                         fprintf(file, "\\pagebreak_top ");
207                 if (pagebreak_bottom)
208                         fprintf(file, "\\pagebreak_bottom ");
209                         
210                 /* Start of appendix? */
211                 if (start_of_appendix)
212                         fprintf(file, "\\start_of_appendix ");
213
214                 /* Noindent? */
215                 if (noindent)
216                         fprintf(file, "\\noindent ");
217                         
218                 /* Alignment? */
219                 if (align != LYX_ALIGN_LAYOUT) {
220                         switch (align) {
221                         case LYX_ALIGN_LEFT: h = 1; break;
222                         case LYX_ALIGN_RIGHT: h = 2; break;
223                         case LYX_ALIGN_CENTER: h = 3; break;
224                         default: h = 0; break;
225                         }
226                         fprintf(file, "\\align %s ", string_align[h]);
227                 }
228                 if (pextra_type != PEXTRA_NONE) {
229                         fprintf(file, "\\pextra_type %d", pextra_type);
230                         if (pextra_type == PEXTRA_MINIPAGE) {
231                                 fprintf(file, " \\pextra_alignment %d",
232                                         pextra_alignment);
233                                 if (pextra_hfill)
234                                         fprintf(file, " \\pextra_hfill %d",
235                                                 pextra_hfill);
236                                 if (pextra_start_minipage)
237                                         fprintf(file, " \\pextra_start_minipage %d",
238                                                 pextra_start_minipage);
239                         }
240                         if (!pextra_width.empty()) {
241                                 fprintf(file, " \\pextra_width %s",
242                                         VSpace(pextra_width).asLyXCommand().c_str());
243                         } else if (!pextra_widthp.empty()) {
244                                 fprintf(file, " \\pextra_widthp %s",pextra_widthp.c_str());
245                         }
246                         fprintf(file,"\n");
247                 }
248         }
249         else {
250                 /* Dummy layout. This means that a footnote ended */
251                 fprintf(file, "\n\\end_float ");
252                 footflag = LyXParagraph::NO_FOOTNOTE;
253         }
254                 
255         /* It might be a table */ 
256         if (table){
257                 fprintf(file, "\\LyXTable\n");
258                 table->Write(file);
259         }
260
261         // bibitem  ale970302
262         if (bibkey)
263                 bibkey->Write(file);
264
265         font1 = LyXFont(LyXFont::ALL_INHERIT);
266
267         column = 0;
268         for (int i = 0; i < last; i++) {
269                 if (!i){
270                         fprintf(file, "\n");
271                         column = 0;
272                 }
273
274                 // Write font changes
275                 font2 = GetFontSettings(i);
276                 if (font2 != font1) {
277                         font2.lyxWriteChanges(font1, file);
278                         column = 0;
279                         font1 = font2;
280                 }
281
282                 c = GetChar(i);
283                 switch (c) {
284                 case LYX_META_INSET:
285                         inset = GetInset(i);
286                         if (inset)
287                                 if (inset->DirectWrite()) {
288                                         // international char, let it write
289                                         // code directly so it's shorter in
290                                         // the file
291                                         inset->Write(file);
292                                 } else {
293                                         fprintf(file, "\n\\begin_inset ");
294                                         inset->Write(file);
295                                         fprintf(file, "\n\\end_inset \n");
296                                         fprintf(file, "\n");
297                                         column = 0;
298                                 }
299                         break;
300                 case LYX_META_NEWLINE: 
301                         fprintf(file, "\n\\newline \n");
302                         column = 0;
303                         break;
304                 case LYX_META_HFILL: 
305                         fprintf(file, "\n\\hfill \n");
306                         column = 0;
307                         break;
308                 case LYX_META_PROTECTED_SEPARATOR: 
309                         fprintf(file, "\n\\protected_separator \n");
310                         column = 0;
311                         break;
312                 case '\\': 
313                         fprintf(file, "\n\\backslash \n");
314                         column = 0;
315                         break;
316                 case '.':
317                         if (i + 1 < last && GetChar(i + 1) == ' ') {
318                                 fprintf(file, ".\n");
319                                 column = 0;
320                         } else
321                                 fprintf(file, ".");
322                         break;
323                 default:
324                         if ((column > 70 && c==' ')
325                             || column > 79){
326                                 fprintf(file, "\n");
327                                 column = 0;
328                         }
329                         // this check is to amend a bug. LyX sometimes
330                         // inserts '\0' this could cause problems.
331                         if (c != '\0')
332                                 fprintf(file, "%c", c);
333                         else
334                                 lyxerr.print("ERROR (LyXParagraph::writeFile):"
335                                              " NULL char in structure.");
336                         column++;
337                         break;
338                 }
339         }
340
341         // now write the next paragraph
342         if (next)
343                 next->writeFile(file, params, footflag, dth);
344 }
345
346
347 void LyXParagraph::validate(LaTeXFeatures &features)
348 {
349         // this will be useful later
350         LyXLayout *layout = lyxstyle.Style(GetCurrentTextClass(), 
351                                            GetLayout());
352         
353         // check the params.
354         if (line_top || line_bottom)
355                 features.lyxline = true;
356         
357         // then the layouts
358         features.layout[GetLayout()] = true;
359
360         // then the fonts
361         FontTable *tmpfonttable = fonttable;
362         while (tmpfonttable) {
363                 if (tmpfonttable->font.noun() == LyXFont::ON) {
364                         lyxerr.debug(LString("font.noun: ") 
365                                      + int(tmpfonttable->font.noun()),
366                                      Error::LATEX);
367                         features.noun = true;
368                         lyxerr.debug("Noun enabled. Font: "
369                                      +tmpfonttable->font.stateText(),
370                                      Error::LATEX);
371                 }
372                 switch (tmpfonttable->font.color()) {
373                 case LyXFont::NONE: 
374                 case LyXFont::INHERIT_COLOR:
375                 case LyXFont::IGNORE_COLOR:
376                         break;
377                 default:
378                         features.color = true;
379                         lyxerr.debug("Color enabled. Font: "
380                                      +tmpfonttable->font.stateText(),
381                                      Error::LATEX);
382                 }
383                 tmpfonttable = tmpfonttable->next;
384         }
385         
386         // then the insets
387         InsetTable *tmpinsettable = insettable;
388         while (tmpinsettable) {
389                 if (tmpinsettable->inset) {
390                         tmpinsettable->inset->Validate(features);
391                 }
392                 tmpinsettable = tmpinsettable->next;
393         }
394         if (table && table->IsLongTable())
395                 features.longtable = true;
396         if (pextra_type == PEXTRA_INDENT)
397                 features.LyXParagraphIndent = true;
398         if (pextra_type == PEXTRA_FLOATFLT)
399                 features.floatflt = true;
400         if (layout->needprotect 
401             && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
402                 features.NeedLyXFootnoteCode = true;
403         if ((current_view->currentBuffer()->params.paragraph_separation == LYX_PARSEP_INDENT) &&
404             (pextra_type == PEXTRA_MINIPAGE))
405                 features.NeedLyXMinipageIndent = true;
406         if (table && table->NeedRotating())
407                 features.rotating = true;
408         if (footnoteflag != NO_FOOTNOTE && footnotekind == ALGORITHM)
409                 features.algorithm = true;
410 }
411
412
413 /* first few functions needed for cut and paste and paragraph breaking */
414 void LyXParagraph::CopyIntoMinibuffer(int pos)
415 {
416         minibuffer_char = GetChar(pos);
417         minibuffer_font = GetFontSettings(pos);
418         minibuffer_inset = 0;
419         if (minibuffer_char == LYX_META_INSET) {
420                 if (GetInset(pos)) {
421                         minibuffer_inset = GetInset(pos)->Clone();
422                 } else {
423                         minibuffer_inset = NULL;
424                         minibuffer_char = ' ';
425                         // This reflects what GetInset() does (ARRae)
426                 }
427         }
428 }
429
430
431 void LyXParagraph::CutIntoMinibuffer(int pos)
432 {
433         minibuffer_char = GetChar(pos);
434         minibuffer_font = GetFontSettings(pos);
435         minibuffer_inset = 0;
436         if (minibuffer_char == LYX_META_INSET) {
437                 if (GetInset(pos)) {
438                         minibuffer_inset = GetInset(pos);
439                         /* This is a little hack since I want exactly the inset,
440                            not just a clone. Otherwise the inset would be deleted
441                            when calling Erase(pos) */
442                         
443                         /* find the entry */ 
444                         InsetTable *tmpi = insettable;
445                         while (tmpi && tmpi->pos != pos) {
446                                 tmpi=tmpi->next;
447                         }
448                         if (tmpi) {  /* This should always be true */
449                                 tmpi->inset = NULL;
450                         }
451                 } else {
452                         minibuffer_inset = NULL;
453                         minibuffer_char = ' ';
454                         // This reflects what GetInset() does (ARRae)
455                 }
456
457         }
458
459         /* Erase(pos); now the caller is responsible for that*/
460 }
461
462
463 void LyXParagraph::InsertFromMinibuffer(int pos)
464 {
465         InsertChar(pos, minibuffer_char);
466         SetFont(pos, minibuffer_font);
467         if (minibuffer_char == LYX_META_INSET)
468                 InsertInset(pos, minibuffer_inset);
469 }
470
471 /* end of minibuffer */ 
472
473
474
475 void LyXParagraph::Clear()
476 {
477         line_top = false;
478         line_bottom = false;
479    
480         pagebreak_top = false;
481         pagebreak_bottom = false;
482
483         added_space_top = VSpace(VSpace::NONE);
484         added_space_bottom = VSpace(VSpace::NONE);
485
486         align = LYX_ALIGN_LAYOUT;
487         depth = 0;
488         noindent = false;
489
490         pextra_type = PEXTRA_NONE;
491         pextra_width.clean();
492         pextra_widthp.clean();
493         pextra_alignment = MINIPAGE_ALIGN_TOP;
494         pextra_hfill = false;
495         pextra_start_minipage = false;
496
497         labelstring.clean();
498         labelwidthstring.clean();
499         layout = 0;
500         bibkey = NULL;
501         
502         start_of_appendix = false;
503 }
504
505
506 /* the destructor removes the new paragraph from the list */ 
507 LyXParagraph::~LyXParagraph()
508 {
509         if (previous)
510                 previous->next = next;
511         if (next)
512                 next->previous = previous;
513
514         if (text)
515                 delete[] text;
516    
517         InsetTable *tmpinset;
518         while (insettable) {
519                 tmpinset = insettable;
520                 insettable = insettable->next;
521                 if (tmpinset->inset)
522                         delete tmpinset->inset;
523                 delete tmpinset;
524                 if (insettable && insettable->next == insettable) {
525                         // somehow this recursion appears occasionally
526                         // but I can't find where.  This bandaid
527                         // helps but isn't the best fix. (ARRae)
528                         if (insettable->inset) {
529                                 delete insettable->inset;
530                         }
531                         delete insettable;
532                         break;
533                 }
534         }
535
536         FontTable *tmpfont;
537         while (fonttable) {
538                 tmpfont = fonttable;
539                 fonttable = fonttable->next;
540                 delete tmpfont;
541         }
542
543         /* table stuff -- begin*/ 
544         if (table)
545                 delete table;
546         /* table stuff -- end*/ 
547
548         // ale970302
549         if (bibkey)
550                 delete bibkey;
551 }
552
553
554 void LyXParagraph::Erase(int pos)
555 {
556         int i;
557
558         /* > because last is the next unused position, and you can 
559          * use it if you want  */
560         if (pos > last) {
561                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
562                         NextAfterFootnote()->Erase(pos - last - 1);
563                 else 
564                         lyxerr.debug("ERROR (LyXParagraph::Erase): position does not exist.");
565                 return;
566         }
567         if (pos < last) { // last is free for insertation, but should be empty
568       
569                 /* if it is an inset, delete the inset entry */ 
570                 if (text[pos] == LYX_META_INSET) {
571                         /* find the entry */ 
572                         InsetTable *tmpi = insettable;
573                         InsetTable *tmpi2 = tmpi;
574                         while (tmpi && tmpi->pos != pos) {
575                                 tmpi2=tmpi;
576                                 tmpi=tmpi->next;
577                         }
578                         if (tmpi) {     // this should always be true
579                                 if (tmpi->inset) // delete the inset if it exists
580                                         delete tmpi->inset;
581                                 if (tmpi == insettable)
582                                         insettable = tmpi->next;
583                                 else 
584                                         tmpi2->next = tmpi->next;
585                                 delete tmpi;
586                         }
587                 }
588
589                 // Shift rest of text      
590                 for (i = pos; i < last - 1; i++) {
591                         text[i]=text[i+1];
592                 }
593                 last--;
594
595                 /* erase entries in the tables */ 
596                 int found = 0;
597                 FontTable *tmp = fonttable;
598                 FontTable *prev = NULL;
599                 while (tmp && !found) {
600                         if (pos >= tmp->pos && pos <= tmp->pos_end)
601                                 found = 1;
602                         else {
603                                 prev = tmp;
604                                 tmp = tmp->next;
605                         }
606                 }
607       
608                 if (found && tmp->pos == tmp->pos_end) {  
609                         /* if it is a multi-character font entry, we just make 
610                          * it smaller (see update below), otherwise we should 
611                          * delete it */
612                         if (prev)
613                                 prev->next = tmp->next;
614                         else
615                                 fonttable = tmp->next;
616          
617                         delete tmp;
618                 }
619
620                 /* update all other entries */
621
622                 tmp = fonttable;
623                 while (tmp) {
624                         if (tmp->pos > pos)
625                                 tmp->pos--;
626                         if (tmp->pos_end >= pos)
627                                 tmp->pos_end--;
628                         tmp = tmp->next;
629                 }
630       
631                 /* update the inset table */ 
632                 InsetTable *tmpi = insettable;
633                 while (tmpi) {
634                         if (tmpi->pos > pos)
635                                 tmpi->pos--;
636                         tmpi=tmpi->next;
637                 }
638       
639         } else {
640                 lyxerr.print("ERROR (LyXParagraph::Erase): can't erase non-existant char.");
641         }
642 }
643
644
645 /* pos is needed to specify the paragraph correctly. Remember the
646 * closed footnotes */ 
647 void LyXParagraph::Enlarge(int pos, int number)
648 {
649         int i;
650
651         /* > because last is the next unused position, and you can 
652          * use it if you want  */
653         if (pos > last) {
654                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
655                         NextAfterFootnote()->Enlarge(pos - last - 1, number);
656                 else 
657                         lyxerr.print("ERROR (LyXParagraph::Enlarge): position does not exist.");
658                 return;
659         }
660
661         if (size - last < number) {
662                 size += number - size + last + STEP_SIZE_PAR;
663                 char *tmp = new char[size];
664                 for (i = 0; i < last; i++)
665                         tmp[i] = text[i];
666                 delete[] text;
667                 text = tmp;
668         }
669 }
670
671
672 /* make the allocated memory fit to the needed size */
673 /* used to make a paragraph smaller */
674 void LyXParagraph::FitSize()
675 {
676         int i;
677   
678         if (size - last > STEP_SIZE_PAR) {
679                 size = last + STEP_SIZE_PAR;
680                 char *tmp = new char[size];
681                 for (i = 0; i < last; i++)
682                         tmp[i] = text[i];
683                 delete[] text;
684                 text = tmp;
685         }
686 }
687
688
689 void LyXParagraph::InsertChar(int pos, char c)
690 {
691         register int i;
692    
693         /* > because last is the next unused position, and you can 
694          * use it if you want  */
695         if (pos > last) {
696                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
697                         NextAfterFootnote()->InsertChar(pos - last - 1, c);
698                 else 
699                         lyxerr.debug("ERROR (LyXParagraph::InsertChar): "
700                                      "position does not exist.");
701                 return;
702         }
703
704         // Are we full? If so, enlarge.
705         if (last == size) {
706                 size += STEP_SIZE_PAR;
707                 char *tmp = new char[size];
708                 for (i = 0; i < last; i++)
709                         tmp[i] = text[i];
710                 delete[] text;
711                 text = tmp;
712         }
713
714         // Shift rest of character
715         for (i = last; i>pos; i--) {
716                 text[i]=text[i-1];
717         }
718
719         text[pos]=c;
720         last++;
721    
722         /* update the font table */ 
723         FontTable *tmp = fonttable;
724         while (tmp) {
725                 if (tmp->pos >= pos)
726                         tmp->pos++;
727                 if (tmp->pos_end >= pos)
728                         tmp->pos_end++;
729                 tmp = tmp->next;
730         }
731    
732         /* update the inset table */ 
733         InsetTable *tmpi = insettable;
734         while (tmpi) {
735                 if (tmpi->pos >= pos)
736                         tmpi->pos++;
737                 tmpi=tmpi->next;
738         }
739 }
740
741
742 void LyXParagraph::InsertInset(int pos, Inset *inset)
743 {
744         /* > because last is the next unused position, and you can 
745          * use it if you want  */
746         if (pos > last) {
747                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
748                         NextAfterFootnote()->InsertInset(pos - last - 1, inset);
749                 else 
750                         lyxerr.print("ERROR (LyXParagraph::InsertInset): " 
751                                      "position does not exist: " + pos);
752                 return;
753         }
754
755         if (text[pos]!=LYX_META_INSET) {
756                 lyxerr.print("ERROR (LyXParagraph::InsertInset): "
757                              "there is no LYX_META_INSET");
758                 return;
759         }
760
761         if (inset) {
762                 /* add a new entry in the inset table */ 
763                 InsetTable *tmpi = new InsetTable;
764                 tmpi->pos = pos;
765                 tmpi->inset = inset;
766                 tmpi->next = insettable;
767                 insettable = tmpi;
768         }
769 }
770
771
772 Inset* LyXParagraph::GetInset(int pos)
773 {
774         if (pos >= last) {
775                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
776                         return NextAfterFootnote()->GetInset(pos - last - 1);
777                 else { 
778                         lyxerr.print(LString("ERROR (LyXParagraph::GetInset): position does not exist: ") + pos);
779                 }
780                 return NULL;
781         }
782
783         /* find the inset */ 
784         InsetTable *tmpi = insettable;
785
786         while (tmpi && tmpi->pos != pos)
787                 tmpi = tmpi->next;
788
789         if (tmpi)
790                 return tmpi->inset;
791         else {
792                 lyxerr.print(LString("ERROR (LyXParagraph::GetInset): "
793                                      "Inset does not exist: ") + pos);
794                 text[pos] = ' '; /// WHY!!! does this set the pos to ' '????
795                 // Did this commenting out introduce a bug? So far I have not
796                 // seen any, please enlighten me. (Lgb)
797                 // My guess is that since the inset does not exist, we might
798                 // as well replace it with a space to prevent crashes. (Asger)
799                 return NULL;
800         }
801 }
802
803
804 // Gets uninstantiated font setting at position.
805 // Optimized after profiling. (Asger)
806 LyXFont LyXParagraph::GetFontSettings(int pos)
807 {
808         if (pos < last) {
809                 FontTable *tmp = fonttable;
810                 while (tmp) {
811                         if (pos >= tmp->pos && pos <= tmp->pos_end) 
812                                 return tmp->font;
813                         tmp = tmp->next;
814                 }
815         }
816
817         /* > because last is the next unused position, and you can 
818          * use it if you want  */
819         else if (pos > last) {
820                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
821                         return NextAfterFootnote()->GetFontSettings(pos - last - 1);
822                 else {
823                         // Why is it an error to ask for the font of a
824                         // position that does not exist? Would it be
825                         // enough for this to be anable on debug?
826                         // We want strict error checking, but it's ok to only
827                         // have it when debugging. (Asger)
828                         lyxerr.print(
829                                 LString("ERROR (LyXParagraph::GetFontSettings): "
830                                         "position does not exist. ") + pos);
831                 }
832         } else if (pos) {
833                 return GetFontSettings(pos - 1);
834         }
835         return LyXFont(LyXFont::ALL_INHERIT);
836 }
837
838
839 // Gets the fully instantiated font at a given position in a paragraph
840 // This is basically the same function as LyXText::GetFont() in text2.C.
841 // The difference is that this one is used for generating the LaTeX file,
842 // and thus cosmetic "improvements" are disallowed: This has to deliver
843 // the true picture of the buffer. (Asger)
844 // If position is -1, we get the layout font of the paragraph.
845 // If position is -2, we get the font of the manual label of the paragraph.
846 LyXFont LyXParagraph::getFont(int pos)
847 {
848         LyXFont tmpfont;
849         LyXLayout *layout = lyxstyle.Style(GetCurrentTextClass(), 
850                                            GetLayout());
851    
852         int main_body=0;
853         if (layout->labeltype == LABEL_MANUAL)
854                 main_body = BeginningOfMainBody();
855
856         if (pos >= 0){
857                 LyXFont layoutfont;
858                 if (pos < main_body)
859                         layoutfont = layout->labelfont;
860                 else
861                         layoutfont = layout->font;
862                 tmpfont = GetFontSettings(pos);
863                 tmpfont.realize(layoutfont);
864         } else {
865                 // process layoutfont for pos == -1 and labelfont for pos < -1
866                 if (pos == -1)
867                         tmpfont = layout->font;
868                 else
869                         tmpfont = layout->labelfont;
870         }
871
872         // check for environment font information
873         char par_depth = GetDepth();
874         LyXParagraph * par = this;
875         while (par && par_depth && !tmpfont.resolved()) {
876                 par = par->DepthHook(par_depth - 1);
877                 if (par) {
878                         tmpfont.realize(lyxstyle.
879                                         Style(GetCurrentTextClass(),
880                                               par->GetLayout())->font);
881                         par_depth = par->GetDepth();
882                 }
883         }
884
885         tmpfont.realize(lyxstyle.TextClass(GetCurrentTextClass())->defaultfont);
886         return tmpfont;
887 }
888
889
890 /// Returns the height of the highest font in range
891 LyXFont::FONT_SIZE LyXParagraph::HighestFontInRange(int startpos, int endpos) const
892 {
893         LyXFont::FONT_SIZE maxsize = LyXFont::SIZE_TINY;
894
895         FontTable *tmp = fonttable;
896         while (tmp) {
897                 if (startpos <= tmp->pos_end && endpos >= tmp->pos) {
898                         LyXFont::FONT_SIZE size = tmp->font.size();
899                         if (size > maxsize && size<=LyXFont::SIZE_HUGER)
900                                 maxsize = size;
901                 }
902                 tmp = tmp->next;
903         }
904         return maxsize;
905 }
906
907
908 char LyXParagraph::GetChar(int pos)
909 {
910 #ifdef DEVEL_VERSION
911         /* a workaround to 'fix' some bugs in text-class */
912         if (pos < 0) {
913                 // This function is important. It should not work around bugs.
914                 // Let's find the bugs instead and fix them. (Asger)
915                 lyxerr.print(LString("FATAL ERROR (LyXParagraph::GetChar):"
916                                      " bad position ") + pos);
917                 abort();
918         }
919 #endif
920
921         if (pos < last) {
922                 return text[pos];
923         }
924
925         /* > because last is the next unused position, and you can 
926          * use it if you want  */
927         else if (pos > last) {
928                 if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) 
929                         return NextAfterFootnote()->GetChar(pos - last - 1);
930                 else 
931                         lyxerr.print("ERROR (LyXParagraph::GetChar): "
932                                      "position does not exist.");
933                 return '\0';
934         } else { // pos==last
935                 /* we should have a footnote environment */ 
936                 if (!next || next->footnoteflag == LyXParagraph::NO_FOOTNOTE) {
937 // Notice that LyX does request the last char from time to time. (Asger)
938 //                      lyxerr.print("ERROR (LyXParagraph::GetChar): "
939 //                                    "expected footnote.");
940                         return '\0';
941                 }
942                 switch (next->footnotekind) {
943                 case LyXParagraph::FOOTNOTE:
944                         return LYX_META_FOOTNOTE;
945                 case LyXParagraph::MARGIN:
946                         return LYX_META_MARGIN;
947                 case LyXParagraph::FIG:
948                 case LyXParagraph::WIDE_FIG:
949                         return LYX_META_FIG;
950                 case LyXParagraph::TAB:
951                 case LyXParagraph::WIDE_TAB:
952                         return LYX_META_TAB;
953                 case LyXParagraph::ALGORITHM:
954                         return LYX_META_ALGORITHM;
955                 }
956 //              if (next->footnotekind == LyXParagraph::FOOTNOTE)
957 //                      return LYX_META_FOOTNOTE;
958 //              if (next->footnotekind == LyXParagraph::MARGIN)
959 //                      return LYX_META_MARGIN;
960 //              if (next->footnotekind == LyXParagraph::FIG)
961 //                      return LYX_META_FIG;
962 //              if (next->footnotekind == LyXParagraph::TAB)
963 //                      return LYX_META_TAB;
964 //              if (next->footnotekind == LyXParagraph::ALGORITHM)
965 //                      return LYX_META_ALGORITHM;
966 //              lyxerr.print("ERROR (LyXParagraph::GetChar): "
967 //                            "unknown footnote kind.");
968 //              return 'F';             /* this should not happen!  */
969                 // This _can_ not happen, due to the type of next->footnotekind
970                 // being LyXParagraph::footnot_kind
971                 return '\0'; // to shut up gcc
972         }
973 }
974
975
976 LString LyXParagraph::GetWord(int & lastpos)
977
978
979   //Added 98/9/21 by REH
980   // return an LString of the current word, and the end of the word
981   // in lastpos.
982
983   // the current word is defined as starting at the first character from
984   // the immediate left of lastpospos which meets the definition of IsLetter(),
985   // continuing to the last character to the right of this meeting
986   // IsLetter.
987
988
989   // i just left this in from GetChar()
990 {
991 #ifdef DEVEL_VERSION
992         /* a workaround to 'fix' some bugs in text-class */
993         if (lastpos < 0) {
994                 // This function is important. It should not work around bugs.
995                 // Let's find the bugs instead and fix them. (Asger)
996                 lyxerr.print(LString("FATAL ERROR (LyXParagraph::GetWord):"
997                                      " bad position ") + lastpos);
998                 abort();
999         }
1000 #endif
1001
1002         LString theword;
1003
1004         // grab a word
1005         
1006         
1007         //i think the devcode aborts before this, but why not be
1008         // versatile?
1009         if (lastpos < 0) lastpos=0; 
1010
1011         
1012         // move back until we have a letter
1013
1014         //there's no real reason to have firstpos & lastpos as
1015         //separate variables as this is written, but maybe someon
1016         // will want to return firstpos in the future.
1017
1018         //since someone might have typed a punctuation first
1019         int firstpos = lastpos;
1020         
1021         while ((firstpos >=0) && !IsLetter(firstpos))
1022                 firstpos--;
1023
1024         // now find the beginning by looking for a nonletter
1025         
1026         while ((firstpos>=0) && IsLetter(firstpos))
1027                 firstpos--;
1028
1029         // the above is now pointing to the preceeding non-letter
1030         firstpos++;
1031         lastpos=firstpos;
1032
1033         // so copy characters into theword  until we get a nonletter
1034         // note that this can easily exceed lastpos, wich means
1035         // that if used in the middle of a word, the whole word
1036         // is included
1037
1038         while (IsLetter(lastpos)) theword += GetChar(lastpos++);
1039         
1040         return  theword;
1041
1042 }
1043
1044
1045 int LyXParagraph::Last()
1046 {
1047         if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1048                 return last + NextAfterFootnote()->Last() + 1;   /* the 1 is the symbol
1049                                                                   * for the footnote */
1050         else
1051                 return last;
1052 }
1053
1054
1055 LyXParagraph *LyXParagraph::ParFromPos(int pos)
1056 {
1057         /* > because last is the next unused position, and you can 
1058          * use it if you want  */
1059         if (pos > last) {
1060                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
1061                         return NextAfterFootnote()->ParFromPos(pos - last - 1);
1062                 else 
1063                         lyxerr.print("ERROR (LyXParagraph::ParFromPos): "
1064                                      "position does not exist.");
1065                 return this;
1066         }
1067         else
1068                 return this;
1069 }
1070
1071
1072 int LyXParagraph::PositionInParFromPos(int pos)
1073 {
1074         /* > because last is the next unused position, and you can 
1075          * use it if you want  */
1076         if (pos > last) {
1077                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) 
1078                         return NextAfterFootnote()->PositionInParFromPos(pos - last - 1);
1079                 else 
1080                         lyxerr.print(
1081                                 "ERROR (LyXParagraph::PositionInParFromPos): "
1082                                 "position does not exist.");
1083                 return pos;
1084         }
1085         else
1086                 return pos;
1087 }
1088
1089
1090 void LyXParagraph::SetFont(int pos, LyXFont const & font)
1091 {
1092         /* > because last is the next unused position, and you can 
1093          * use it if you want  */
1094         if (pos > last) {
1095                 if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1096                         NextAfterFootnote()->SetFont(pos - last - 1, font);
1097                 } else {
1098                         lyxerr.print("ERROR (LyXParagraph::SetFont): "
1099                                      "position does not exist.");
1100                 }
1101                 return;
1102         }
1103
1104         LyXFont patternfont(LyXFont::ALL_INHERIT);
1105
1106 // First, reduce font against layout/label font
1107 // Update: The SetCharFont() routine in text2.C already reduces font, so
1108 // we don't need to do that here. (Asger)
1109 // No need to simplify this because it will disappear in a new kernel. (Asger)
1110
1111         // Next search font table
1112         FontTable *tmp2;
1113
1114         bool found = false;
1115         FontTable *tmp = fonttable;
1116         while (tmp && !found) {
1117                 if (pos >= tmp->pos && pos <= tmp->pos_end)
1118                         found = true;
1119                 else
1120                         tmp = tmp->next;
1121         }
1122
1123         if (!found) {
1124                 /* if we did not find a font entry, but if the font at hand
1125                  * is the same as default, we just forget it */
1126                 if (font == patternfont)
1127                         return;
1128
1129                 /* ok, we did not find a font entry. But maybe there is exactly
1130                  * the needed font entry one position left */ 
1131                 found = false;
1132                 tmp2 = fonttable;
1133                 while (tmp2 && !found) {
1134                         if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1135                                 found = true;
1136                         else
1137                                 tmp2 = tmp2->next;
1138                 }
1139                 if (found) {
1140                         /* ok there is one. maybe it is exactly the needed font */
1141                         if (tmp2->font == font) {
1142                                 /* put the position under the font */ 
1143                                 tmp2->pos_end++;
1144                                 return;
1145                         }
1146                 }
1147                 /* Add a new entry in the 
1148                  * fonttable for the position */
1149                 tmp = new FontTable;
1150                 tmp->pos = pos;
1151                 tmp->pos_end = pos;
1152                 tmp->font = patternfont;
1153                 tmp->next = fonttable;
1154                 fonttable = tmp;
1155         }
1156         else {
1157                 /* we found a font entry. maybe we have to split it and create
1158                  * a new one */ 
1159
1160                 if (tmp->pos != tmp->pos_end) {  /* more than one character  */
1161
1162                         if (pos == tmp->pos) {
1163                                 /* maybe we could enlarge the left fonttable */ 
1164
1165                                 found = false;
1166                                 tmp2 = fonttable;
1167                                 while (tmp2 && !found) {
1168                                         if (pos - 1 >= tmp2->pos && pos - 1 <= tmp2->pos_end)
1169                                                 found = true;
1170                                         else
1171                                                 tmp2 = tmp2->next;
1172                                 }
1173
1174                                 /* Is there is one, and is it exactly the needed font? */
1175                                 if (found && tmp2->font == font) {
1176                                         /* put the position under the font */ 
1177                                         tmp2->pos_end++;
1178                                         tmp->pos++;
1179                                         return;
1180                                 }
1181
1182                                 /* Add a new entry in the 
1183                                  * fonttable for the position */
1184                                 tmp2 = new FontTable;
1185                                 tmp2->pos = pos + 1;
1186                                 tmp2->pos_end = tmp->pos_end;
1187                                 tmp2->font = tmp->font;
1188                                 tmp->pos_end = pos;
1189                                 tmp2->next = fonttable;
1190                                 fonttable = tmp2;
1191                         }
1192                         else if (pos == tmp->pos_end) {
1193                                 /* Add a new entry in the 
1194                                  * fonttable for the position */
1195                                 tmp2 = new FontTable;
1196                                 tmp2->pos = tmp->pos;
1197                                 tmp2->pos_end = tmp->pos_end - 1;
1198                                 tmp2->font = tmp->font;
1199                                 tmp->pos = tmp->pos_end;
1200                                 tmp2->next = fonttable;
1201                                 fonttable = tmp2;
1202                         }
1203                         else {
1204                                 /* Add a new entry in the 
1205                                  * fonttable for the position */
1206                                 tmp2 = new FontTable;
1207                                 tmp2->pos = tmp->pos;
1208                                 tmp2->pos_end = pos - 1;
1209                                 tmp2->font = tmp->font;
1210                                 tmp2->next = fonttable;
1211                                 fonttable = tmp2;
1212             
1213                                 tmp2 = new FontTable;
1214                                 tmp2->pos = pos + 1;
1215                                 tmp2->pos_end = tmp->pos_end;
1216                                 tmp2->font = tmp->font;
1217                                 tmp2->next = fonttable;
1218                                 fonttable = tmp2;
1219             
1220                                 tmp->pos = pos;
1221                                 tmp->pos_end = pos;
1222                         }
1223                 }
1224         }
1225
1226         tmp->font = font;
1227 }
1228
1229    
1230 /* this function is able to hide closed footnotes */
1231 LyXParagraph *LyXParagraph::Next()
1232 {
1233         LyXParagraph *tmp;
1234         if (next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1235                 tmp = next;
1236                 while (tmp && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1237                         tmp = tmp->next;
1238                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1239                         return tmp->Next(); /* there can be more than one footnote
1240                                              * in a logical paragraph */
1241                 else
1242                         return next;    /* this should never happen! */
1243         }
1244         else
1245                 return next;
1246 }
1247
1248
1249 LyXParagraph *LyXParagraph::NextAfterFootnote()
1250 {
1251         LyXParagraph *tmp;
1252         if (next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1253                 tmp = next;
1254                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1255                         tmp = tmp->next;
1256                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1257                         return tmp;            /* there can be more than one footnote
1258                                                 * in a logical paragraph */
1259                 else
1260                         return next;                   /* this should never happen! */
1261         }
1262         else
1263                 return next;
1264 }
1265
1266
1267 LyXParagraph *LyXParagraph::PreviousBeforeFootnote()
1268 {
1269         LyXParagraph *tmp;
1270         if (previous && previous->footnoteflag != LyXParagraph::NO_FOOTNOTE) {
1271                 tmp = next;
1272                 while (tmp && tmp->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1273                         tmp = tmp->previous;
1274                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1275                         return tmp;            /* there can be more than one footnote
1276                                                 * in a logical paragraph */
1277                 else
1278                         return previous;                       /* this should never happen! */
1279         }
1280         else
1281                 return previous;
1282 }
1283
1284
1285 LyXParagraph *LyXParagraph::LastPhysicalPar()
1286 {
1287         LyXParagraph *tmp;
1288         if (footnoteflag != LyXParagraph::NO_FOOTNOTE)
1289                 return this;
1290    
1291         tmp = this;
1292         while (tmp->next && tmp->next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1293                 tmp = tmp->NextAfterFootnote();
1294    
1295         return tmp;
1296    
1297 }
1298
1299
1300 LyXParagraph *LyXParagraph::FirstPhysicalPar()
1301 {
1302         if (!IsDummy())
1303                 return this;
1304         LyXParagraph *tmppar = this;
1305
1306         while (tmppar && (tmppar->IsDummy()
1307                           || tmppar->footnoteflag != LyXParagraph::NO_FOOTNOTE))
1308                 tmppar = tmppar->previous;
1309    
1310         if (!tmppar)
1311                 return this;           /* this should never happen!  */
1312         else
1313                 return tmppar;
1314 }
1315
1316
1317 /* this function is able to hide closed footnotes */
1318 LyXParagraph *LyXParagraph::Previous()
1319 {
1320         LyXParagraph *tmp = previous;
1321         if (!tmp)
1322                 return tmp;
1323    
1324         if (tmp->previous && tmp->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1325                 tmp = tmp->previous;
1326                 while (tmp && tmp->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1327                         tmp = tmp->previous;
1328                 if (tmp && tmp->footnoteflag != LyXParagraph::CLOSED_FOOTNOTE) 
1329                         return tmp->next->Previous();   
1330
1331                 else
1332                         return previous; 
1333         }
1334         else
1335                 return previous;
1336 }
1337
1338    
1339 void LyXParagraph::BreakParagraph(int pos, int flag)
1340 {
1341         int i, pos_end, pos_first;
1342
1343         /* create a new paragraph */
1344         LyXParagraph *par = ParFromPos(pos);
1345         LyXParagraph *firstpar = FirstPhysicalPar();
1346    
1347         LyXParagraph *tmp = new LyXParagraph(par);
1348    
1349         tmp->footnoteflag = footnoteflag;
1350         tmp->footnotekind = footnotekind;
1351    
1352         /* this is an idea for a more userfriendly layout handling, I will
1353          * see what the users say */
1354    
1355         /* layout stays the same with latex-environments */ 
1356         if (flag) {
1357                 tmp->SetOnlyLayout(firstpar->layout);
1358                 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1359         }
1360
1361         if (Last() > pos || !Last() || flag == 2) {
1362                 tmp->SetOnlyLayout(firstpar->layout);
1363                 tmp->align = firstpar->align;
1364                 tmp->SetLabelWidthString(firstpar->labelwidthstring);
1365       
1366                 tmp->line_bottom = firstpar->line_bottom;
1367                 firstpar->line_bottom = false;
1368                 tmp->pagebreak_bottom = firstpar->pagebreak_bottom;
1369                 firstpar->pagebreak_bottom = false;
1370                 tmp->added_space_bottom = firstpar->added_space_bottom;
1371                 firstpar->added_space_bottom = VSpace(VSpace::NONE);
1372       
1373                 tmp->depth = firstpar->depth;
1374                 tmp->noindent = firstpar->noindent;
1375    
1376                 /* copy everything behind the break-position to the new paragraph */
1377                 pos_first = 0;
1378                 while (ParFromPos(pos_first) != par)
1379                         pos_first++;
1380    
1381                 pos_end = pos_first + par->last - 1;
1382    
1383                 /* make sure there is enough memory for the now larger
1384                    paragraph. This is not neccessary, because
1385                    InsertFromMinibuffer will enlarge the memory (it uses
1386                    InsertChar of course). But doing it by hand
1387                    is MUCH faster! (only one time, not thousend times!!) */
1388
1389                 tmp->Enlarge(0, pos_end - pos);
1390
1391                 for (i = pos; i <= pos_end; i++) {
1392                         par->CutIntoMinibuffer(i - pos_first);
1393                         tmp->InsertFromMinibuffer(i - pos);
1394                 }
1395
1396                 for (i = pos_end; i >= pos; i--)
1397                         par->Erase(i - pos_first);
1398                 /* free memory of the now shorter paragraph*/
1399                 par->FitSize();
1400         }
1401
1402         /* just an idea of me */ 
1403         if (!pos) {
1404                 tmp->line_top = firstpar->line_top;
1405                 tmp->pagebreak_top = firstpar->pagebreak_top;
1406                 tmp->added_space_top = firstpar->added_space_top;
1407                 tmp->bibkey = firstpar->bibkey;
1408                 firstpar->Clear();
1409                 /* layout stays the same with latex-environments */ 
1410                 if (flag) {
1411                         firstpar->SetOnlyLayout(tmp->layout);
1412                         firstpar->SetLabelWidthString(tmp->labelwidthstring);
1413                         firstpar->depth = tmp->depth;
1414                 }
1415         }
1416 }
1417
1418
1419 void LyXParagraph::MakeSameLayout(LyXParagraph *par)
1420 {
1421         par = par->FirstPhysicalPar();
1422         footnoteflag = par->footnoteflag;
1423         footnotekind = par->footnotekind;
1424
1425         layout = par->layout;
1426         align = par-> align;
1427         SetLabelWidthString(par->labelwidthstring);
1428
1429         line_bottom = par->line_bottom;
1430         pagebreak_bottom = par->pagebreak_bottom;
1431         added_space_bottom = par->added_space_bottom;
1432
1433         line_top = par->line_top;
1434         pagebreak_top = par->pagebreak_top;
1435         added_space_top = par->added_space_top;
1436
1437         pextra_type = par->pextra_type;
1438         pextra_width = par->pextra_width;
1439         pextra_widthp = par->pextra_widthp;
1440         pextra_alignment = par->pextra_alignment;
1441         pextra_hfill = par->pextra_hfill;
1442         pextra_start_minipage = par->pextra_start_minipage;
1443
1444         noindent = par->noindent;
1445         depth = par->depth;
1446 }
1447
1448
1449 LyXParagraph *LyXParagraph::FirstSelfrowPar()
1450 {
1451         LyXParagraph *tmppar;
1452    
1453         tmppar = this;
1454         while (tmppar && (
1455                 (tmppar->IsDummy() && tmppar->previous->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE)
1456                 || tmppar->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE))
1457                 tmppar = tmppar->previous;
1458    
1459         if (!tmppar)
1460                 return this;           /* this should never happen!  */
1461         else
1462                 return tmppar;
1463 }
1464
1465
1466 LyXParagraph *LyXParagraph::Clone()
1467 {
1468         int i;
1469    
1470         /* create a new paragraph */
1471         LyXParagraph *result = new LyXParagraph();
1472    
1473         result->MakeSameLayout(this);
1474
1475         /* this is because of the dummy layout of the paragraphs that
1476            follow footnotes */
1477         result->layout = layout;
1478    
1479         /* table stuff -- begin*/ 
1480         if (table)
1481                 result->table = table->Clone();
1482         else
1483                 result->table = NULL;
1484         /* table stuff -- end*/ 
1485    
1486         // ale970302
1487         result->bibkey = (bibkey) ? new InsetBibKey(bibkey): 0;
1488                
1489     
1490         /* copy everything behind the break-position to the new paragraph */
1491    
1492         /* make shure there is enough memory for the now larger paragraph.
1493          * This is not neccessary, because InsertFromMinibuffer will enlarge
1494          * the memory (it uses InsertChar of course). But doing it by hand
1495          * is MUCH faster! (only one time, not thousend times!!) */
1496    
1497         result->Enlarge(0, last+2);
1498    
1499         for (i = 0; i < last; i++) {
1500                 CopyIntoMinibuffer(i);
1501                 result->InsertFromMinibuffer(i);
1502         }
1503         return result;
1504 }
1505
1506
1507 bool LyXParagraph::HasSameLayout(LyXParagraph* par)
1508 {
1509         par = par->FirstPhysicalPar();
1510
1511         return (
1512                 par->footnoteflag == footnoteflag &&
1513                 par->footnotekind == footnotekind &&
1514
1515                 par->layout == layout &&
1516
1517                 par->align == align &&
1518
1519                 par->line_bottom == line_bottom &&
1520                 par->pagebreak_bottom == pagebreak_bottom &&
1521                 par->added_space_bottom == added_space_bottom &&
1522
1523                 par->line_top == line_top &&
1524                 par->pagebreak_top == pagebreak_top &&
1525                 par->added_space_top == added_space_top &&
1526
1527                 par->pextra_type == pextra_type &&
1528                 par->pextra_width == pextra_width && 
1529                 par->pextra_widthp == pextra_widthp && 
1530                 par->pextra_alignment == pextra_alignment && 
1531                 par->pextra_hfill == pextra_hfill && 
1532                 par->pextra_start_minipage == pextra_start_minipage && 
1533
1534                 par->table == table && // what means: NO TABLE AT ALL 
1535
1536                 par->noindent == noindent &&
1537                 par->depth == depth);
1538 }
1539
1540
1541 void LyXParagraph::BreakParagraphConservative(int pos)
1542 {
1543         int i, pos_end, pos_first;
1544    
1545         /* create a new paragraph */
1546         LyXParagraph *par = ParFromPos(pos);
1547
1548         LyXParagraph *tmp = new LyXParagraph(par);
1549    
1550         tmp->MakeSameLayout(par);
1551    
1552         if (Last() > pos) {   
1553                 /* copy everything behind the break-position to the new
1554                    paragraph */
1555                 pos_first = 0;
1556                 while (ParFromPos(pos_first) != par)
1557                         pos_first++;
1558    
1559                 pos_end = pos_first + par->last - 1;
1560    
1561                 /* make shure there is enough memory for the now larger
1562                    paragraph. This is not neccessary, because
1563                    InsertFromMinibuffer will enlarge the memory (it uses
1564                    InsertChar of course). But doing it by hand
1565                    is MUCH faster! (only one time, not thousend times!!) */
1566    
1567                 tmp->Enlarge(0, pos_end - pos);
1568    
1569                 for (i = pos; i <= pos_end; i++) {
1570       
1571                         par->CutIntoMinibuffer(i - pos_first);
1572                         tmp->InsertFromMinibuffer(i - pos);
1573                 }
1574                 for (i = pos_end; i >= pos; i--)
1575                         par->Erase(i - pos_first);
1576
1577                 /* free memory of the now shorter paragraph*/
1578                 par->FitSize();
1579         }
1580 }
1581    
1582
1583 /* be carefull, this does not make any check at all */ 
1584 void LyXParagraph::PasteParagraph()
1585 {
1586         int i, pos_end, pos_insert;
1587         LyXParagraph *the_next;
1588    
1589         /* copy the next paragraph to this one */
1590         the_next = Next();
1591    
1592         LyXParagraph *firstpar = FirstPhysicalPar();
1593    
1594         /* first the DTP-stuff */ 
1595         firstpar->line_bottom = the_next->line_bottom;
1596         firstpar->added_space_bottom = the_next->added_space_bottom;
1597         firstpar->pagebreak_bottom = the_next->pagebreak_bottom;
1598    
1599         pos_end = the_next->last - 1;
1600         pos_insert = Last();
1601    
1602         /* enlarge the paragraph. This is faster than enlarge it
1603          * every 10th insertion. */ 
1604         if (pos_end >= 0)
1605                 Enlarge(pos_insert, pos_end);
1606       
1607         /* ok, now copy the paragraph */ 
1608         for (i = 0; i <= pos_end; i++) {
1609                 the_next->CutIntoMinibuffer(i);
1610                 InsertFromMinibuffer(pos_insert + i);
1611         }
1612    
1613         /* delete the next paragraph */
1614         delete the_next;
1615 }
1616
1617
1618 void LyXParagraph::OpenFootnote(int pos)
1619 {
1620         LyXParagraph *par = ParFromPos(pos);
1621         par = par->next;
1622         while (par && par->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1623                 par->footnoteflag = LyXParagraph::OPEN_FOOTNOTE;
1624                 par = par->next;
1625         }
1626 }
1627
1628
1629 void LyXParagraph::CloseFootnote(int pos)
1630 {
1631         LyXParagraph *par = ParFromPos(pos);
1632         par = par->next;
1633         while (par && par->footnoteflag == LyXParagraph::OPEN_FOOTNOTE) {
1634                 par->footnoteflag = LyXParagraph::CLOSED_FOOTNOTE;
1635                 par = par->next;
1636         }
1637 }
1638
1639
1640 int LyXParagraph::GetLayout()
1641 {
1642         return FirstPhysicalPar()->layout;
1643 }
1644
1645
1646 char LyXParagraph::GetDepth()
1647 {
1648         return FirstPhysicalPar()->depth;
1649 }
1650
1651
1652 char LyXParagraph::GetAlign()
1653 {
1654         return FirstPhysicalPar()->align;
1655 }
1656
1657
1658 LString LyXParagraph::GetLabelString()
1659 {
1660         return FirstPhysicalPar()->labelstring;
1661 }
1662
1663
1664 int LyXParagraph::GetFirstCounter(int i)
1665 {
1666         return FirstPhysicalPar()->counter[i];
1667 }
1668
1669
1670 /* the next two functions are for the manual labels */ 
1671 LString LyXParagraph::GetLabelWidthString()
1672 {
1673         if (!FirstPhysicalPar()->labelwidthstring.empty())
1674                 return FirstPhysicalPar()->labelwidthstring;
1675         else
1676                 return _("Senseless with this layout!");
1677 }
1678
1679
1680 void LyXParagraph::SetLabelWidthString(LString const & s)
1681 {
1682         LyXParagraph *par = FirstPhysicalPar();
1683
1684         par->labelwidthstring = s;
1685 }
1686
1687
1688 void LyXParagraph::SetOnlyLayout(char new_layout)
1689 {
1690         LyXParagraph
1691                 *par = FirstPhysicalPar(),
1692                 *ppar = NULL,
1693                 *npar = NULL;
1694
1695         par->layout = new_layout;
1696         /* table stuff -- begin*/ 
1697         if (table) 
1698                 par->layout = 0;
1699         /* table stuff -- end*/ 
1700         if (par->pextra_type == PEXTRA_NONE) {
1701                 if (par->Previous()) {
1702                         ppar = par->Previous()->FirstPhysicalPar();
1703                         while(ppar
1704                               && ppar->Previous()
1705                               && (ppar->depth > par->depth))
1706                                 ppar = ppar->Previous()->FirstPhysicalPar();
1707                 }
1708                 if (par->Next()) {
1709                         npar = par->Next()->NextAfterFootnote();
1710                         while(npar
1711                               && npar->Next()
1712                               && (npar->depth > par->depth))
1713                                 npar = npar->Next()->NextAfterFootnote();
1714                 }
1715                 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1716                         LString
1717                                 p1 = ppar->pextra_width,
1718                                 p2 = ppar->pextra_widthp;
1719                         ppar->SetPExtraType(ppar->pextra_type,
1720                                             p1.c_str(),p2.c_str());
1721                 }
1722                 if ((par->pextra_type == PEXTRA_NONE) &&
1723                     npar && (npar->pextra_type != PEXTRA_NONE)) {
1724                         LString
1725                                 p1 = npar->pextra_width,
1726                                 p2 = npar->pextra_widthp;
1727                         npar->SetPExtraType(npar->pextra_type,
1728                                             p1.c_str(),p2.c_str());
1729                 }
1730         }
1731 }
1732
1733
1734 void LyXParagraph::SetLayout(char new_layout)
1735 {
1736         LyXParagraph
1737                 *par = FirstPhysicalPar(),
1738                 *ppar = NULL,
1739                 *npar = NULL;
1740
1741         par->layout = new_layout;
1742         par->labelwidthstring.clean();
1743         par->align = LYX_ALIGN_LAYOUT;
1744         //par->depth = 0;
1745         par->added_space_top = VSpace(VSpace::NONE);
1746         par->added_space_bottom = VSpace(VSpace::NONE);
1747         /* table stuff -- begin*/ 
1748         if (table) 
1749                 par->layout = 0;
1750         /* table stuff -- end*/
1751         if (par->pextra_type == PEXTRA_NONE) {
1752                 if (par->Previous()) {
1753                         ppar = par->Previous()->FirstPhysicalPar();
1754                         while(ppar
1755                               && ppar->Previous()
1756                               && (ppar->depth > par->depth))
1757                                 ppar = ppar->Previous()->FirstPhysicalPar();
1758                 }
1759                 if (par->Next()) {
1760                         npar = par->Next()->NextAfterFootnote();
1761                         while(npar
1762                               && npar->Next()
1763                               && (npar->depth > par->depth))
1764                                 npar = npar->Next()->NextAfterFootnote();
1765                 }
1766                 if (ppar && (ppar->pextra_type != PEXTRA_NONE)) {
1767                         LString
1768                                 p1 = ppar->pextra_width,
1769                                 p2 = ppar->pextra_widthp;
1770                         ppar->SetPExtraType(ppar->pextra_type,
1771                                             p1.c_str(),p2.c_str());
1772                 }
1773                 if ((par->pextra_type == PEXTRA_NONE) &&
1774                     npar && (npar->pextra_type != PEXTRA_NONE)) {
1775                         LString
1776                                 p1 = npar->pextra_width,
1777                                 p2 = npar->pextra_widthp;
1778                         npar->SetPExtraType(npar->pextra_type,
1779                                             p1.c_str(),p2.c_str());
1780                 }
1781         }
1782 }
1783
1784
1785 /* if the layout of a paragraph contains a manual label, the beginning of the 
1786 * main body is the beginning of the second word. This is what the par-
1787 * function returns. If the layout does not contain a label, the main
1788 * body always starts with position 0. This differentiation is necessary,
1789 * because there cannot be a newline or a blank <= the beginning of the 
1790 * main body in TeX. */ 
1791
1792 int LyXParagraph::BeginningOfMainBody()
1793 {
1794         if (FirstPhysicalPar() != this)
1795                 return -1;
1796    
1797         int i = 0;
1798    
1799 //      while (i < last   &&  !(i > 1 && GetChar(i-1)==' ')
1800 //             && GetChar(i)!=LYX_META_NEWLINE)
1801 //              i++;
1802 // Unroll the first two cycles of this loop
1803 // and remember the previous character to remove unnecessary GetChar() calls
1804
1805         if (i < last
1806             && GetChar(i) != LYX_META_NEWLINE) {
1807                 ++i;
1808                 char previous_char, temp;
1809                 if (i < last
1810                     && (previous_char = GetChar(i)) != LYX_META_NEWLINE) {
1811                         // Yes, this  ^ is supposed to be "=" not "=="
1812                         ++i;
1813                         while (i < last
1814                                && previous_char != ' '
1815                                && (temp = GetChar(i)) != LYX_META_NEWLINE) {
1816                                 ++i;
1817                                 previous_char = temp;
1818                         }
1819                 }
1820         }
1821
1822         if (i==0 && i == last &&
1823             !(footnoteflag==LyXParagraph::NO_FOOTNOTE
1824               && next && next->footnoteflag != LyXParagraph::NO_FOOTNOTE)
1825                 )
1826                 i++;                           /* the cursor should not jump  
1827                                                 * to the main body if there
1828                                                 * is nothing in! */
1829         return i;
1830 }
1831
1832
1833 LyXParagraph* LyXParagraph::DepthHook(int deth)
1834 {
1835         LyXParagraph *newpar = this;
1836         if (deth < 0)
1837                 return NULL;
1838    
1839         do {
1840                 newpar = newpar->FirstPhysicalPar()->Previous();
1841         } while (newpar && newpar->GetDepth() > deth
1842                  && newpar->footnoteflag == footnoteflag);
1843    
1844         if (!newpar) {
1845                 if (Previous() || GetDepth())
1846                         lyxerr.print("ERROR (LyXParagraph::DepthHook): "
1847                                      "no hook.");
1848                 newpar = this;
1849         }
1850         return newpar->FirstPhysicalPar();
1851 }
1852
1853
1854 int LyXParagraph::AutoDeleteInsets()
1855 {
1856         InsetTable *tmpi = insettable;
1857         InsetTable *tmpi2 = tmpi;
1858         int i=0;
1859         while (tmpi) {
1860                 tmpi2 = tmpi;
1861                 tmpi = tmpi->next;
1862                 if (tmpi2->inset)
1863                         if (tmpi2->inset->AutoDelete()) {
1864                                 i++;
1865                                 Erase(tmpi2->pos);
1866                         } else {}
1867                 else
1868                         lyxerr.print(
1869                                 "ERROR (LyXParagraph::AutoDeleteInsets): "
1870                                 "cannot auto-delete insets");
1871         }
1872         return i;
1873 }
1874
1875
1876 Inset* LyXParagraph::ReturnNextInsetPointer(int &pos)
1877 {
1878         InsetTable *tmpi = insettable;
1879         InsetTable *tmpi2 = NULL;
1880         while (tmpi){
1881                 if (tmpi->pos >= pos) {
1882                         if (!tmpi2 || tmpi->pos < tmpi2->pos)
1883                                 tmpi2 = tmpi;
1884                 }
1885                 tmpi=tmpi->next;
1886         }
1887         if (tmpi2){
1888                 pos = tmpi2->pos;
1889                 return tmpi2->inset;
1890         }
1891         else
1892                 return NULL;
1893 }
1894
1895
1896 /* returns -1 if inset not found */
1897 int LyXParagraph::GetPositionOfInset(Inset* inset)
1898 {
1899         /* find the entry */ 
1900         InsetTable *tmpi = insettable;
1901         while (tmpi && tmpi->inset != inset) {
1902                 tmpi=tmpi->next;
1903         }
1904         if (tmpi && tmpi->inset)
1905                 return tmpi->pos;
1906         else{
1907                 /* think about footnotes */
1908                 if (footnoteflag == LyXParagraph::NO_FOOTNOTE 
1909                     && next && next->footnoteflag == LyXParagraph::CLOSED_FOOTNOTE) {
1910                         int further =
1911                                 NextAfterFootnote()->GetPositionOfInset(inset);
1912                         if (further != -1)
1913                                 return last + 1 + further;
1914                 }
1915                 return -1;
1916         }
1917 }
1918
1919
1920 void LyXParagraph::readSimpleWholeFile(FILE *myfile)
1921 {
1922         char c;
1923
1924         FileInfo fileInfo(fileno(myfile));
1925         long file_size = fileInfo.getSize();
1926         /* it is horrible, I know, but faster.
1927          * I should not use InsertString for that :-( */
1928    
1929         /* I will write a better insertion in the future */ 
1930         Enlarge(0, file_size + 10);
1931    
1932         rewind(myfile);
1933    
1934         if (!feof(myfile)) {
1935                 do {
1936                         c = fgetc(myfile);
1937                         InsertChar(last,c);
1938                 } while (!feof(myfile));
1939       
1940         }
1941 }
1942
1943
1944 LyXParagraph* LyXParagraph::TeXOnePar(LString &file, TexRow &texrow,
1945                                       LString &foot, TexRow &foot_texrow,
1946                                       int &foot_count)
1947 {
1948         lyxerr.debug(LString("TeXOnePar...     ") + (long)this, Error::LATEX);
1949         LyXParagraph *par = next;
1950         LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), layout);
1951
1952         bool further_blank_line = false;
1953         if (IsDummy())
1954                 lyxerr.print("ERROR (LyXParagraph::TeXOnePar) is dummy.");
1955
1956         if (start_of_appendix) {
1957                 file += "\\appendix\n";
1958                 texrow.newline();
1959         }
1960
1961         if (tex_code_break_column && style->isCommand()){
1962                 file += '\n';
1963                 texrow.newline();
1964         }
1965
1966         if (pagebreak_top) {
1967                 file += "\\newpage";
1968                 further_blank_line = true;
1969         }
1970         if (added_space_top.kind() != VSpace::NONE) {
1971                 file += added_space_top.asLatexCommand();
1972                 further_blank_line = true;
1973         }
1974       
1975         if (line_top) {
1976                 file += "\\lyxline{\\" + getFont(0).latexSize() + '}';
1977                 file += "\\vspace{-1\\parskip}";
1978                 further_blank_line = true;
1979         }
1980
1981         if (further_blank_line){
1982                 file += '\n';
1983                 texrow.newline();
1984         }
1985
1986         switch (style->latextype) {
1987         case LATEX_COMMAND:
1988                 file += '\\';
1989                 file += style->latexname;
1990                 file += style->latexparam;
1991                 break;
1992         case LATEX_ITEM_ENVIRONMENT:
1993                 if (bibkey) 
1994                         bibkey->Latex(file, false);
1995                 else
1996                         file += "\\item ";
1997                 break;
1998         case LATEX_LIST_ENVIRONMENT:
1999                 file += "\\item ";
2000                 break;
2001         default:
2002                 break;
2003         }
2004
2005         bool need_par = SimpleTeXOnePar(file, texrow);
2006  
2007         // Spit out footnotes
2008         while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE
2009                && par->footnoteflag != footnoteflag) {
2010                 par = par->TeXFootnote(file, texrow,
2011                                        foot, foot_texrow, foot_count);
2012                 par->SimpleTeXOnePar(file, texrow);
2013                 par = par->next;
2014         }
2015
2016         // Make sure that \\par is done with the font of the last
2017         // character if this has another size as the default.
2018         // This is necessary because LaTeX (and LyX on the screen)
2019         // calculates the space between the baselines according
2020         // to this font. (Matthias)
2021         LyXFont font = getFont(Last()-1);
2022         if (need_par) {
2023                 if (style->resfont.size() != font.size()) {
2024                         file += '\\';
2025                         file += font.latexSize();
2026                         file += ' ';
2027                 }
2028                 file += "\\par}";
2029         } else if (lyxstyle.Style(GetCurrentTextClass(),
2030                                   GetLayout())->isCommand()){
2031                 if (style->resfont.size() != font.size()) {
2032                         file += '\\';
2033                         file += font.latexSize();
2034                         file += ' ';
2035                 }
2036                 file += '}';
2037         } else if (style->resfont.size() != font.size()){
2038                 file += "{\\" + font.latexSize() + " \\par}";
2039         }
2040         
2041         switch (style->latextype) {
2042         case LATEX_ITEM_ENVIRONMENT:
2043         case LATEX_LIST_ENVIRONMENT:
2044                 if (par && (depth < par->depth)) {
2045                         file += '\n';
2046                         texrow.newline();
2047                 }
2048                 break;
2049         case LATEX_ENVIRONMENT:
2050                 // if its the last paragraph of the current environment
2051                 // skip it otherwise fall through
2052                 if (par
2053                     && (par->layout != layout
2054                         || par->depth != depth
2055                         || par->pextra_type != pextra_type))
2056                         break;
2057         default:
2058                 if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE
2059                       && footnotekind != LyXParagraph::FOOTNOTE
2060                       && footnotekind != LyXParagraph::MARGIN
2061                       && (table
2062                           || (par
2063                               && par->table)))) {
2064                         // don't insert this if we would be adding it
2065                         // before or after a table in a float.  This 
2066                         // little trick is needed in order to allow
2067                         // use of tables in \subfigures or \subtables.
2068                         file += '\n';
2069                         texrow.newline();
2070                 }
2071         }
2072         
2073         further_blank_line = false;
2074         if (line_bottom) {
2075                 file += "\\lyxline{\\" + getFont(Last()-1).latexSize() + '}';
2076                 further_blank_line = true;
2077         }
2078
2079         if (added_space_bottom.kind() != VSpace::NONE) {
2080                 file += added_space_bottom.asLatexCommand();
2081                 further_blank_line = true;
2082         }
2083       
2084         if (pagebreak_bottom) {
2085                 file += "\\newpage";
2086                 further_blank_line = true;
2087         }
2088
2089         if (further_blank_line){
2090                 file += '\n';
2091                 texrow.newline();
2092         }
2093
2094         if (!(footnoteflag != LyXParagraph::NO_FOOTNOTE && par &&
2095               par->footnoteflag == LyXParagraph::NO_FOOTNOTE) // &&
2096 //            (pextra_type != PEXTRA_MINIPAGE ||
2097 /*             (par && !par->pextra_type == PEXTRA_MINIPAGE)) */ ) {
2098                 file += '\n';
2099                 texrow.newline();
2100         }
2101
2102         lyxerr.debug(LString("TeXOnePar...done ") + (long)par, Error::LATEX);
2103         return par;
2104 }
2105
2106
2107 // This one spits out the text of the paragraph
2108 bool LyXParagraph::SimpleTeXOnePar(LString &file, TexRow &texrow)
2109 {
2110         lyxerr.debug(LString("SimpleTeXOnePar...     ") + (long)this, 
2111                      Error::LATEX);
2112
2113         if (table)
2114                 return SimpleTeXOneTablePar(file, texrow);
2115
2116         char c;
2117         int main_body;
2118         int column;
2119         
2120         bool return_value = false;
2121         //bool underbar = false;
2122
2123         LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2124         LyXFont basefont;
2125
2126         /* maybe we have to create a optional argument */ 
2127         if (style->labeltype != LABEL_MANUAL)
2128                 main_body = 0;
2129         else
2130                 main_body = BeginningOfMainBody();
2131
2132         if (main_body > 0) {
2133                 file += '[';
2134                 basefont = getFont(-2); // Get label font
2135         } else {
2136                 basefont = getFont(-1); // Get layout font
2137         }
2138
2139         column = 0;
2140
2141         if (main_body >= 0
2142             && !last
2143             && !IsDummy()) {
2144                 if (style->isCommand()) {
2145                         file += '{';
2146                         column++;
2147                 } else if (align != LYX_ALIGN_LAYOUT) {
2148                         file += '{';
2149                         column++;
2150                         return_value = true;
2151                 }
2152         }
2153  
2154         // Which font is currently active?
2155         LyXFont running_font = basefont;
2156         // Do we have an open font change?
2157         bool open_font = false;
2158
2159         texrow.start(this, 0);
2160  
2161         for (int i = 0; i < last; i++) {
2162                 column++;
2163                 // First char in paragraph or after label?
2164                 if (i == main_body && !IsDummy()) {
2165                         if (main_body > 0) {
2166                                 if (open_font) {
2167                                         column += running_font.latexWriteEndChanges(file, basefont);
2168                                         open_font = false;
2169                                 }
2170                                 basefont = getFont(-1); // Now use the layout font
2171                                 running_font = basefont;
2172                                 file += ']';
2173                                 column++;
2174                         }
2175                         if (style->isCommand()) {
2176                                 file += '{';
2177                                 column++;
2178                         } else if (align != LYX_ALIGN_LAYOUT) {
2179                                 file += "{\\par";
2180                                 column += 4;
2181                                 return_value = true;
2182                         }
2183
2184                         if (noindent) {
2185                                 file += "\\noindent ";
2186                                 column += 10;
2187                         }
2188                         switch (align) {
2189                         case LYX_ALIGN_LEFT:
2190                                 file += "\\raggedright ";
2191                                 column+=13;
2192                                 break;
2193                         case LYX_ALIGN_RIGHT:
2194                                 file += "\\raggedleft ";
2195                                 column+=12;
2196                                 break;
2197                         case LYX_ALIGN_CENTER:
2198                                 file += "\\centering ";
2199                                 column+=11;
2200                                 break;
2201                         }        
2202                 }
2203
2204                 c = GetChar(i);
2205
2206                 // Fully instantiated font
2207                 LyXFont font = getFont(i);
2208
2209                 // Spaces at end of font change are simulated to be
2210                 // outside font change, i.e. we write "\textXX{text} "
2211                 // rather than "\textXX{text }". (Asger) 
2212                 if (open_font && c == ' ' && i <= last-2 
2213                     && !getFont(i+1).equalExceptLatex(running_font) 
2214                     && !getFont(i+1).equalExceptLatex(font)) {
2215                         font = getFont(i+1);
2216                 }
2217
2218                 // We end font definition before blanks
2219                 if (!font.equalExceptLatex(running_font) && open_font) {
2220                         column += running_font.latexWriteEndChanges(file, basefont);
2221                         running_font = basefont;
2222                         open_font = false;
2223                 }
2224
2225                 // Blanks are printed before start of fontswitch
2226                 if (c == ' '){
2227                         // Do not print the separation of the optional argument
2228                         if (i != main_body - 1) {
2229                                 SimpleTeXBlanks(file, texrow, i, column, font, style);
2230                         }
2231                 }
2232
2233                 // Do we need to change font?
2234                 if (!font.equalExceptLatex(running_font)
2235                     && i != main_body-1) {
2236                         column += font.latexWriteStartChanges(file, basefont);
2237                         running_font = font;
2238                         open_font = true;
2239                 }
2240
2241                 if (c == LYX_META_NEWLINE) {
2242                         // newlines are handled differently here than
2243                         // the default in SimpleTeXSpecialChars().
2244                         if (!style->newline_allowed
2245                             || font.latex() == LyXFont::ON) {
2246                                 file += '\n';
2247                         } else {
2248                                 if (open_font) {
2249                                         column += running_font.latexWriteEndChanges(file, basefont);
2250                                         open_font = false;
2251                                 }
2252                                 basefont = getFont(-1);
2253                                 running_font = basefont;
2254                                 if (font.family() == 
2255                                     LyXFont::TYPEWRITER_FAMILY) {
2256                                         file += "~";
2257                                 }
2258                                 file += "\\\\\n";
2259                         }
2260                         texrow.newline();
2261                         texrow.start(this, i+1);
2262                         column = 0;
2263                 } else {
2264                         SimpleTeXSpecialChars(file, texrow,
2265                                               font, running_font, basefont,
2266                                               open_font, style, i, column, c);
2267                 }
2268         }
2269
2270         // If we have an open font definition, we have to close it
2271         if (open_font) {
2272                 running_font.latexWriteEndChanges(file, basefont);
2273         }
2274
2275         /* needed if there is an optional argument but no contents */ 
2276         if (main_body > 0 && main_body == last) {
2277                 file += "]~";
2278                 return_value = false;
2279         }
2280
2281         lyxerr.debug(LString("SimpleTeXOnePar...done ") + (long)this, 
2282                      Error::LATEX);
2283         return return_value;
2284 }
2285
2286
2287 // This one spits out the text of a table paragraph
2288 bool LyXParagraph::SimpleTeXOneTablePar(LString &file, TexRow &texrow)
2289 {
2290         lyxerr.debug(LString("SimpleTeXOneTablePar...     ")+
2291                      (long)this, Error::LATEX);
2292         char c;
2293         int column, tmp;
2294    
2295         bool return_value = false;
2296         int current_cell_number = -1;
2297
2298         LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2299         LyXFont basefont;
2300
2301         basefont = getFont(-1); // Get layout font
2302         // Which font is currently active?
2303         LyXFont running_font = basefont;
2304         // Do we have an open font change?
2305         bool open_font = false;
2306  
2307         column = 0;
2308         if (!IsDummy()) { // it is dummy if it is in a float!!!
2309                 if (style->isCommand()) {
2310                         file += '{';
2311                         column++;
2312                 } else if (align != LYX_ALIGN_LAYOUT) {
2313                         file += '{';
2314                         column++;
2315                         return_value = true;
2316                 }
2317                 if (noindent) {
2318                         file += "\\noindent ";
2319                         column += 10;
2320                 }
2321                 switch (align) {
2322                 case LYX_ALIGN_LEFT:
2323                         file += "\\raggedright ";
2324                         column+=13;
2325                         break;
2326                 case LYX_ALIGN_RIGHT:
2327                         file += "\\raggedleft ";
2328                         column+=12;
2329                         break;
2330                 case LYX_ALIGN_CENTER:
2331                         file += "\\centering ";
2332                         column+=11;
2333                         break;
2334                 }
2335         }
2336         current_cell_number = -1;
2337         tmp = table->TexEndOfCell(file,current_cell_number);
2338         for (;tmp>0;tmp--)
2339                 texrow.newline();
2340         
2341         texrow.start(this, 0);
2342
2343         for (int i = 0; i < last; i++) {
2344                 c = GetChar(i);
2345                 if (table->IsContRow(current_cell_number+1)) {
2346                         if (c == LYX_META_NEWLINE)
2347                                 current_cell_number++;
2348                         continue;
2349                 }
2350                 column++;
2351                 
2352                 // Fully instantiated font
2353                 LyXFont font = getFont(i);
2354
2355                 // Spaces at end of font change are simulated to be outside font change.
2356                 // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2357                 if (open_font && c == ' ' && i <= last-2 
2358                     && getFont(i+1) != running_font && getFont(i+1) != font) {
2359                         font = getFont(i+1);
2360                 }
2361
2362                 // We end font definition before blanks
2363                 if (font != running_font && open_font) {
2364                         column += running_font.latexWriteEndChanges(file, basefont);
2365                         running_font = basefont;
2366                         open_font = false;
2367                 }
2368                 // Blanks are printed before start of fontswitch
2369                 if (c == ' '){
2370                         SimpleTeXBlanks(file, texrow, i, column, font, style);
2371                 }
2372                 // Do we need to change font?
2373                 if (font != running_font) {
2374                         column += font.latexWriteStartChanges(file, basefont);
2375                         running_font = font;
2376                         open_font = true;
2377                 }
2378                 // Do we need to turn on LaTeX mode?
2379                 if (font.latex() != running_font.latex()) {
2380                         if (font.latex() == LyXFont::ON
2381                             && style->needprotect) {
2382                                 file += "\\protect ";
2383                                 column += 9;
2384                         }
2385                 }
2386                 if (c == LYX_META_NEWLINE) {
2387                         // special case for inside a table
2388                         // different from default case in SimpleTeXSpecialChars()
2389                         if (open_font) {
2390                                 column += running_font.latexWriteEndChanges(file, basefont);
2391                                 open_font = false;
2392                         }
2393                         basefont = getFont(-1);
2394                         running_font = basefont;
2395                         current_cell_number++;
2396                         if (table->CellHasContRow(current_cell_number) >= 0) {
2397                                 TeXContTableRows(file, i+1, current_cell_number, column, texrow);
2398                         }
2399                         // if this cell follow only ContRows till end don't
2400                         // put the EndOfCell because it is put after the
2401                         // for(...)
2402                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2403                             current_cell_number--;
2404                             break;
2405                         }
2406                         int tmp = table->TexEndOfCell(file, current_cell_number);
2407                         if (tmp>0) {
2408                                 column = 0;
2409                         } else if (tmp < 0) {
2410                                 tmp = -tmp;
2411                         }
2412                         for (;tmp--;) {
2413                                 texrow.newline();
2414                         }
2415                         texrow.start(this, i+1);
2416                 } else {
2417                         SimpleTeXSpecialChars(file, texrow,
2418                                               font, running_font, basefont,
2419                                               open_font, style, i, column, c);
2420                 }
2421         }
2422
2423         // If we have an open font definition, we have to close it
2424         if (open_font) {
2425                 running_font.latexWriteEndChanges(file, basefont);
2426         }
2427         current_cell_number++;
2428         tmp = table->TexEndOfCell(file, current_cell_number);
2429         for (;tmp>0;tmp--)
2430                 texrow.newline();
2431         lyxerr.debug(LString("SimpleTeXOneTablePar...done ")+(long)this, Error::LATEX);
2432         return return_value;
2433 }
2434
2435
2436 // This one spits out the text off ContRows in tables
2437 bool LyXParagraph::TeXContTableRows(LString &file, int i,
2438                                     int current_cell_number,
2439                                     int &column, TexRow &texrow)
2440 {
2441        lyxerr.debug(LString("TeXContTableRows...     ") +
2442                     (long)this, Error::LATEX);
2443         if (!table)
2444                 return false;
2445     
2446         char c;
2447         int cell;
2448         int lastpos;
2449    
2450         bool return_value = false;
2451         LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2452         LyXFont basefont;
2453
2454         basefont = getFont(-1); // Get layout font
2455         // Which font is currently active?
2456         LyXFont running_font = basefont;
2457         // Do we have an open font change?
2458         bool open_font = false;
2459
2460         lastpos = i;
2461         cell = table->CellHasContRow(current_cell_number);
2462         current_cell_number++;
2463         while(cell >= 0) {
2464                 // first find the right position
2465                 i = lastpos;
2466                 for (; (i<last) && (current_cell_number<cell); i++) {
2467                         c = GetChar(i);
2468                         if (c == LYX_META_NEWLINE)
2469                                 current_cell_number++;
2470                 }
2471                 lastpos = i;
2472                 c=GetChar(i);
2473                 if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2474                         file += " \\\\\n";
2475                         texrow.newline();
2476                         column = 0;
2477                 } else if ((c != ' ') && (c != LYX_META_NEWLINE)) {
2478                         file += ' ';
2479                 }
2480                 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
2481                         column++;
2482
2483                         // Fully instantiated font
2484                         LyXFont font = getFont(i);
2485
2486                         // Spaces at end of font change are simulated to be outside font change.
2487                         // i.e. we write "\textXX{text} " rather than "\textXX{text }". (Asger)
2488                         if (open_font && c == ' ' && i <= last-2 
2489                             && getFont(i+1) != running_font && getFont(i+1) != font) {
2490                                 font = getFont(i+1);
2491                         }
2492
2493                         // We end font definition before blanks
2494                         if (font != running_font && open_font) {
2495                                 column += running_font.latexWriteEndChanges(file, basefont);
2496                                 running_font = basefont;
2497                                 open_font = false;
2498                         }
2499                         // Blanks are printed before start of fontswitch
2500                         if (c == ' '){
2501                                 SimpleTeXBlanks(file, texrow, i, column, font, style);
2502                         }
2503                         // Do we need to change font?
2504                         if (font != running_font) {
2505                                 column += font.latexWriteStartChanges(file, basefont);
2506                                 running_font = font;
2507                                 open_font = true;
2508                         }
2509                         // Do we need to turn on LaTeX mode?
2510                         if (font.latex() != running_font.latex()) {
2511                                 if (font.latex() == LyXFont::ON
2512                                     && style->needprotect)
2513                                         {
2514                                                 file += "\\protect ";
2515                                                 column += 9;
2516                                         }
2517                         }
2518                         SimpleTeXSpecialChars(file, texrow, font, running_font, basefont,
2519                                               open_font, style, i, column, c);
2520                 }
2521                 // If we have an open font definition, we have to close it
2522                 if (open_font) {
2523                         running_font.latexWriteEndChanges(file, basefont);
2524                         open_font = false;
2525                 }
2526                 basefont = getFont(-1);
2527                 running_font = basefont;
2528                 cell = table->CellHasContRow(current_cell_number);
2529         }
2530         lyxerr.debug(LString("TeXContTableRows...done ")+(long)this, Error::LATEX);
2531         return return_value;
2532 }
2533
2534
2535 bool LyXParagraph::linuxDocConvertChar(char c, LString &sgml_string)
2536 {
2537         bool retval = false;
2538         switch (c) {
2539         case LYX_META_HFILL:
2540                 sgml_string.clean();
2541                 break;
2542         case LYX_META_PROTECTED_SEPARATOR: 
2543                 sgml_string = ' ';
2544                 break;
2545         case LYX_META_NEWLINE:
2546                 sgml_string = '\n';
2547                 break;
2548         case '&': 
2549                 sgml_string = "&amp;";
2550                 break;
2551         case '<': 
2552                 sgml_string = "&lt;"; 
2553                 break;
2554         case '>':
2555                 sgml_string = "&gt;"; 
2556                 break;
2557         case '$': 
2558                 sgml_string = "&dollar;"; 
2559                 break;
2560         case '#': 
2561                 sgml_string = "&num;";
2562                 break;
2563         case '%': 
2564                 sgml_string = "&percnt;";
2565                 break;
2566         case '[': 
2567                 sgml_string = "&lsqb;";
2568                 break;
2569         case ']': 
2570                 sgml_string = "&rsqb;";
2571                 break;
2572         case '{': 
2573                 sgml_string = "&lcub;";
2574                 break;
2575         case '}': 
2576                 sgml_string = "&rcub;";
2577                 break;
2578         case '~': 
2579                 sgml_string = "&tilde;";
2580                 break;
2581         case '"': 
2582                 sgml_string = "&dquot;";
2583                 break;
2584         case '\\': 
2585                 sgml_string = "&bsol;";
2586                 break;
2587         case ' ':
2588                 retval = true;
2589                 sgml_string = ' ';
2590                 break;
2591         case '\0': /* Ignore :-) */
2592                 sgml_string.clean();
2593                 break;
2594         default:
2595                 sgml_string = c;
2596                 break;
2597         }
2598         return retval;
2599 }
2600
2601 void LyXParagraph::SimpleDocBookOneTablePar(LString &file, LString &extra,
2602                                             int & desc_on, int depth) 
2603 {
2604         if (!table)
2605                 return;
2606         lyxerr.debug(LString("SimpleDocbookOneTablePar...     ") +
2607                      (long)this, Error::LATEX);
2608         int column, tmp;
2609         bool return_value = false;
2610         int current_cell_number = -1;
2611         LyXFont font1,font2;
2612         char c;
2613         Inset *inset;
2614         int main_body, j;
2615         LString emph="emphasis";
2616         bool emph_flag=false;
2617         int char_line_count=0;
2618         
2619         LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2620         
2621         if (style->labeltype != LABEL_MANUAL)
2622                 main_body = 0;
2623         else
2624                 main_body = BeginningOfMainBody();
2625         
2626         /* gets paragraph main font */
2627         if (main_body > 0)
2628                 font1 = style->labelfont;
2629         else
2630                 font1 = style->font;
2631         
2632         char_line_count = depth;
2633         addNewlineAndDepth(file, depth);
2634         if (footnoteflag == LyXParagraph::NO_FOOTNOTE) {
2635                 file += "<INFORMALTABLE>";
2636                 addNewlineAndDepth(file, ++depth);
2637         }
2638         current_cell_number = -1;
2639         tmp = table->DocBookEndOfCell(file,current_cell_number, depth);
2640         
2641         /* parsing main loop */
2642         for (int i = 0; i < last; i++) {
2643                 c = GetChar(i);
2644                 if (table->IsContRow(current_cell_number+1)) {
2645                         if (c == LYX_META_NEWLINE)
2646                                 current_cell_number++;
2647                         continue;
2648                 }
2649                 column++;
2650                 
2651                 // Fully instantiated font
2652                 font2 = getFont(i);
2653                 
2654                 /* handle <emphasis> tag */
2655                 if (font1.emph() != font2.emph() && i) {
2656                         if (font2.emph() == LyXFont::ON) {
2657                                 file += "<emphasis>";
2658                                 emph_flag=true;
2659                         } else if (emph_flag) {
2660                                 file += "</emphasis>";
2661                                 emph_flag=false;
2662                         }
2663                 }
2664                 if (c == LYX_META_NEWLINE) {
2665                         // we have only to control for emphasis open here!
2666                         if (emph_flag) {
2667                                 file += "</emphasis>";
2668                                 emph_flag=false;
2669                         }
2670                         font1 = font2 = getFont(-1);
2671                         current_cell_number++;
2672                         if (table->CellHasContRow(current_cell_number) >= 0) {
2673                                 DocBookContTableRows(file, extra, desc_on, i+1,
2674                                                      current_cell_number,
2675                                                      column);
2676                         }
2677                         // if this cell follow only ContRows till end don't
2678                         // put the EndOfCell because it is put after the
2679                         // for(...)
2680                         if (table->ShouldBeVeryLastCell(current_cell_number)) {
2681                                 current_cell_number--;
2682                                 break;
2683                         }
2684                         tmp=table->DocBookEndOfCell(file, current_cell_number,
2685                                                     depth);
2686                         
2687                         if (tmp > 0)
2688                                 column = 0;
2689                 } else if (c == LYX_META_INSET) {
2690                         inset = GetInset(i);
2691                         LString tmp_out;
2692                         inset->DocBook(tmp_out);
2693                         //
2694                         // This code needs some explanation:
2695                         // Two insets are treated specially
2696                         //   label if it is the first element in a command paragraph
2697                         //         desc_on==3
2698                         //   graphics inside tables or figure floats can't go on
2699                                 //   title (the equivalente in latex for this case is caption
2700                         //   and title should come first
2701                         //         desc_on==4
2702                         //
2703                         if(desc_on!=3 || i!=0) {
2704                                 if(tmp_out[0]=='@') {
2705                                         if(desc_on==4)
2706                                                 extra += tmp_out.frontStrip('@');
2707                                         else
2708                                                 file += tmp_out.frontStrip('@');
2709                                 } else
2710                                         file += tmp_out;
2711                         }
2712                 } else if (font2.latex() == LyXFont::ON) {
2713                         // "TeX"-Mode on ==> SGML-Mode on.
2714                         if (c!='\0')
2715                                 file += c;
2716                         char_line_count++;
2717                 } else {
2718                         LString sgml_string;
2719                         if (linuxDocConvertChar(c, sgml_string) 
2720                             && !style->free_spacing) {
2721                                 // in freespacing mode, spaces are
2722                                 // non-breaking characters
2723                                 // char is ' '
2724                                 if (desc_on == 1) {
2725                                         char_line_count++;
2726                                         file += '\n';
2727                                         file += "</term><listitem><para>";
2728                                         desc_on = 2;
2729                                 } else  {
2730                                         file += c;
2731                                 }
2732                         } else {
2733                                 file += sgml_string;
2734                         }
2735                 }
2736                 font1 = font2;
2737         }
2738         
2739         /* needed if there is an optional argument but no contents */ 
2740         if (main_body > 0 && main_body == last) {
2741                 font1 = style->font;
2742         }
2743         
2744         if (emph_flag) {
2745                 file += "</emphasis>";
2746         }
2747         
2748         current_cell_number++;
2749         tmp = table->DocBookEndOfCell(file, current_cell_number, depth);
2750         /* resets description flag correctly */
2751         switch(desc_on){
2752         case 1:
2753                 /* <term> not closed... */
2754                 file += "</term>";
2755                 break;
2756         }
2757         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
2758                 file += "</INFORMALTABLE>";
2759         file += '\n';
2760         lyxerr.debug(LString("SimpleDocbookOneTablePar...done ") +
2761                      (long)this, Error::LATEX);
2762 }
2763
2764 void LyXParagraph::DocBookContTableRows(LString &file, LString &extra,
2765                                         int & desc_on, int i,
2766                                         int current_cell_number, int &column) 
2767 {
2768         if (!table)
2769                 return;
2770         
2771         lyxerr.debug(LString("DocBookContTableRows... ") +
2772                      (long)this, Error::LATEX);
2773         int tmp, cell, lastpos;
2774         LyXFont font1,font2;
2775         char c;
2776         Inset *inset;
2777         int main_body, j;
2778         LString emph="emphasis";
2779         bool emph_flag=false;
2780         int char_line_count=0;
2781         
2782         LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), GetLayout());
2783         
2784         if (style->labeltype != LABEL_MANUAL)
2785                 main_body = 0;
2786         else
2787                 main_body = BeginningOfMainBody();
2788         
2789         /* gets paragraph main font */
2790         if (main_body > 0)
2791                 font1 = style->labelfont;
2792         else
2793                 font1 = style->font;
2794         
2795         lastpos = i;
2796         cell = table->CellHasContRow(current_cell_number);
2797         current_cell_number++;
2798         while(cell >= 0) {
2799                 // first find the right position
2800                 i = lastpos;
2801                 for (; (i<last) && (current_cell_number<cell); i++) {
2802                         c = GetChar(i);
2803                         if (c == LYX_META_NEWLINE)
2804                                 current_cell_number++;
2805                 }
2806                 lastpos = i;
2807                 c=GetChar(i);
2808                 // I don't know how to handle this so I comment it
2809                 // for the moment (Jug)
2810 //             if (table->Linebreaks(table->FirstVirtualCell(cell))) {
2811 //                     file += " \\\\\n";
2812 //                     column = 0;
2813 //             } else
2814                 if ((c != ' ') && (c != LYX_META_NEWLINE)) {
2815                         file += ' ';
2816                 }
2817                 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
2818                         column++;
2819                         
2820                         // Fully instantiated font
2821                         font2 = getFont(i);
2822                         
2823                         /* handle <emphasis> tag */
2824                         if (font1.emph() != font2.emph() && i) {
2825                                 if (font2.emph() == LyXFont::ON) {
2826                                         file += "<emphasis>";
2827                                         emph_flag=true;
2828                                 } else if (emph_flag) {
2829                                         file += "</emphasis>";
2830                                         emph_flag=false;
2831                                 }
2832                         }
2833                         if (c == LYX_META_INSET) {
2834                                 inset = GetInset(i);
2835                                 LString tmp_out;
2836                                 inset->DocBook(tmp_out);
2837                                 //
2838                                 // This code needs some explanation:
2839                                 // Two insets are treated specially
2840                                 //   label if it is the first element in a command paragraph
2841                                 //       desc_on==3
2842                                 //   graphics inside tables or figure floats can't go on
2843                                 //   title (the equivalente in latex for this case is caption
2844                                 //   and title should come first
2845                                 //       desc_on==4
2846                                 //
2847                                 if(desc_on!=3 || i!=0) {
2848                                         if(tmp_out[0]=='@') {
2849                                                 if(desc_on==4)
2850                                                         extra += tmp_out.frontStrip('@');
2851                                                 else
2852                                                         file += tmp_out.frontStrip('@');
2853                                         } else
2854                                                 file += tmp_out;
2855                                 }
2856                         } else if (font2.latex() == LyXFont::ON) {
2857                                 // "TeX"-Mode on ==> SGML-Mode on.
2858                                 if (c!='\0')
2859                                         file += c;
2860                                 char_line_count++;
2861                         } else {
2862                                 LString sgml_string;
2863                                 if (linuxDocConvertChar(c, sgml_string) 
2864                                     && !style->free_spacing) {
2865                                 // in freespacing mode, spaces are
2866                                 // non-breaking characters
2867                                 // char is ' '
2868                                         if (desc_on == 1) {
2869                                                 char_line_count++;
2870                                                 file += '\n';
2871                                                 file += "</term><listitem><para>";
2872                                                 desc_on = 2;
2873                                         } else  {
2874                                                 file += c;
2875                                         }
2876                                 } else {
2877                                         file += sgml_string;
2878                                 }
2879                         }
2880                 }
2881                 // we have only to control for emphasis open here!
2882                 if (emph_flag) {
2883                         file += "</emphasis>";
2884                         emph_flag=false;
2885                 }
2886                 font1 = font2 = getFont(-1);
2887                 cell = table->CellHasContRow(current_cell_number);
2888         }
2889         lyxerr.debug(LString("DocBookContTableRows...done ") +
2890                      (long)this, Error::LATEX);
2891 }
2892
2893
2894 //
2895 void LyXParagraph::SimpleTeXBlanks(LString &file, TexRow &texrow,
2896                                    int const i, int &column, LyXFont const &font,
2897                                    LyXLayout const * const style)
2898 {
2899         if (column > tex_code_break_column
2900             && i 
2901             && GetChar(i-1) != ' '
2902             && (i < last-1)
2903             // In LaTeX mode, we don't want to
2904             // break lines since some commands
2905             // do not like this
2906             && ! (font.latex() == LyXFont::ON)
2907             // same in FreeSpacing mode
2908             && !style->free_spacing
2909             // In typewriter mode, we want to avoid 
2910             // ! . ? : at the end of a line
2911             && !(font.family() == LyXFont::TYPEWRITER_FAMILY
2912                  && (GetChar(i-1) == '.'
2913                      || GetChar(i-1) == '?' 
2914                      || GetChar(i-1) == ':'
2915                      || GetChar(i-1) == '!'))) {
2916                 if (tex_code_break_column == 0) {
2917                         // in batchmode we need LaTeX to still
2918                         // see it as a space not as an extra '\n'
2919                         file += " %\n";
2920                 } else {
2921                         file += '\n';
2922                 }
2923                 texrow.newline();
2924                 texrow.start(this, i+1);
2925                 column = 0;
2926         } else if (font.latex() == LyXFont::OFF) {
2927                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
2928                         file += '~';
2929                 } else {
2930                         file += ' ';
2931                 }
2932         }
2933 }
2934
2935
2936 //
2937 void LyXParagraph::SimpleTeXSpecialChars(LString &file, TexRow &texrow,
2938                                          LyXFont &font, LyXFont &running_font, LyXFont &basefont,
2939                                          bool &open_font, LyXLayout const * const style,
2940                                          int &i, int &column, char const c)
2941 {
2942         Inset* inset;
2943
2944         // Two major modes:  LaTeX or plain
2945         // Handle here those cases common to both modes
2946         // and then split to handle the two modes separately.
2947         switch (c) {
2948         case LYX_META_INSET:
2949                 inset = GetInset(i);
2950                 if (inset) {
2951                         int len = file.length();
2952                         int tmp = inset->Latex(file, style->isCommand());
2953                         
2954                         if (tmp) {
2955                                 column = 0;
2956                         } else {
2957                                 column += file.length() - len;
2958                         }
2959                         for (;tmp--;) {
2960                                 texrow.newline();
2961                         }
2962                 }
2963                 break;
2964
2965         case LYX_META_NEWLINE:
2966                 if (open_font) {
2967                         column += running_font.latexWriteEndChanges(file, basefont);
2968                         open_font = false;
2969                 }
2970                 basefont = getFont(-1);
2971                 running_font = basefont;
2972                 break;
2973
2974         case LYX_META_HFILL: 
2975                 file += "\\hfill{}";
2976                 column += 7;
2977                 break;
2978
2979         default:
2980                 // And now for the special cases within each mode
2981                 // Are we in LaTeX mode?
2982                 if (font.latex() == LyXFont::ON) {
2983                         // at present we only have one option
2984                         // but I'll leave it as a switch statement
2985                         // so its simpler to extend. (ARRae)
2986                         switch (c) {
2987                         case LYX_META_PROTECTED_SEPARATOR: 
2988                                 file += ' ';
2989                                 break;
2990
2991                         default:
2992                                 // make sure that we will not print
2993                                 // error generating chars to the tex
2994                                 // file. This test would not be needed
2995                                 // if it were done in the buffer
2996                                 // itself.
2997                                 if (c != '\0') {
2998                                         file += c;
2999                                 }
3000                                 break;
3001                         }
3002                 } else {
3003                         // Plain mode (i.e. not LaTeX)
3004                         switch (c) {
3005                         case LYX_META_PROTECTED_SEPARATOR: 
3006                                 file += '~';
3007                                 break;
3008
3009                         case '\\': 
3010                                 file += "\\textbackslash{}";
3011                                 column += 15;
3012                                 break;
3013                 
3014                         case '°': case '±': case '²': case '³':  
3015                         case '×': case '÷': case '¹': case 'ª':
3016                         case 'º': case '¬': case 'µ':
3017                                 if (current_view->currentBuffer()->params.inputenc == "latin1") {
3018                                         file += "\\ensuremath{";
3019                                         file += c;
3020                                         file += '}';
3021                                         column += 13;
3022                                 } else {
3023                                         file += c;
3024                                 }
3025                                 break;
3026
3027                         case '|': case '<': case '>':
3028                                 // In T1 encoding, these characters exist
3029                                 if (lyxrc->fontenc == "T1") {
3030                                         file += c;
3031                                         //... but we should avoid ligatures
3032                                         if ((c == '>' || c == '<')
3033                                             && i <= last-2
3034                                             && GetChar(i+1) == c){
3035                                                 file += "\\textcompwordmark{}";
3036                                                 column += 19;
3037                                         }
3038                                         break;
3039                                 }
3040                                 // Typewriter font also has them
3041                                 if (font.family() == LyXFont::TYPEWRITER_FAMILY) {
3042                                         file += c;
3043                                         break;
3044                                 } 
3045                                 // Otherwise, we use what LaTeX
3046                                 // provides us.
3047                                 switch(c) {
3048                                 case '<':
3049                                         file += "\\textless{}";
3050                                         column += 10;
3051                                         break;
3052                                 case '>':
3053                                         file += "\\textgreater{}";
3054                                         column += 13;
3055                                         break;
3056                                 case '|':
3057                                         file += "\\textbar{}";
3058                                         column += 9;
3059                                         break;
3060                                 }
3061                                 break;
3062
3063                         case '-': // "--" in Typewriter mode -> "-{}-"
3064                                 if (i <= last-2
3065                                     && GetChar(i+1) == '-'
3066                                     && font.family() == LyXFont::TYPEWRITER_FAMILY) {
3067                                         file += "-{}";
3068                                         column += 2;
3069                                 } else {
3070                                         file += '-';
3071                                 }
3072                                 break;
3073
3074                         case '\"': 
3075                                 file += "\\char`\\\"{}";
3076                                 column += 9;
3077                                 break;
3078
3079                         case '£':
3080                                 if (current_view->currentBuffer()->params.inputenc == "default") {
3081                                         file += "\\pounds{}";
3082                                         column += 8;
3083                                 } else {
3084                                         file += c;
3085                                 }
3086                                 break;
3087
3088                         case '$': case '&':
3089                         case '%': case '#': case '{':
3090                         case '}': case '_':
3091                                 file += '\\';
3092                                 file += c;
3093                                 column += 1;
3094                                 break;
3095
3096                         case '^': case '~':
3097                                 file += '\\';
3098                                 file += c;
3099                                 file += "{}";
3100                                 column += 3;
3101                                 break;
3102
3103                         case '*': case '[': case ']':
3104                                 // avoid being mistaken for optional arguments
3105                                 file += '{';
3106                                 file += c;
3107                                 file += '}';
3108                                 column += 2;
3109                                 break;
3110
3111                         case ' ':
3112                                 /* blanks are printed before font switching */
3113                                 // Sure? I am not! (try nice-latex)
3114                                 // I am sure it's correct. LyX might be smarter
3115                                 // in the future, but for now, nothing wrong is
3116                                 // written. (Asger)
3117                                 break;
3118
3119                         default:
3120                                 /* idea for labels --- begin*/
3121                                 /* check for LyX */
3122                                 if (c ==  'L'
3123                                     && i <= last-3
3124                                     && font.family() != LyXFont::TYPEWRITER_FAMILY
3125                                     && GetChar(i+1) == 'y'
3126                                     && GetChar(i+2) == 'X') {
3127                                         file += "\\LyX{}";
3128                                         i += 2;
3129                                         column += 5;
3130                                 }
3131                                 /* check for TeX */ 
3132                                 else if (c == 'T'
3133                                          && i <= last-3
3134                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3135                                          && GetChar(i+1) == 'e'
3136                                          && GetChar(i+2) == 'X') {
3137                                         file += "\\TeX{}";
3138                                         i += 2;
3139                                         column += 5;
3140                                 }
3141                                 /* check for LaTeX2e */ 
3142                                 else if (c == 'L'
3143                                          && i <= last-7
3144                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3145                                          && GetChar(i+1) == 'a'
3146                                          && GetChar(i+2) == 'T'
3147                                          && GetChar(i+3) == 'e'
3148                                          && GetChar(i+4) == 'X'
3149                                          && GetChar(i+5) == '2'
3150                                          && GetChar(i+6) == 'e') {
3151                                         file += "\\LaTeXe{}";
3152                                         i += 6;
3153                                         column += 8;
3154                                 }
3155                                 /* check for LaTeX */ 
3156                                 else if (c == 'L'
3157                                          && i <= last-5
3158                                          && font.family() != LyXFont::TYPEWRITER_FAMILY
3159                                          && GetChar(i+1) == 'a'
3160                                          && GetChar(i+2) == 'T'
3161                                          && GetChar(i+3) == 'e'
3162                                          && GetChar(i+4) == 'X') {
3163                                         file += "\\LaTeX{}";
3164                                         i += 4;
3165                                         column += 7;
3166                                         /* idea for labels --- end*/ 
3167                                 } else if (c != '\0') {
3168                                         file += c;
3169                                 }
3170                                 break;
3171                         }
3172                 }
3173         }
3174 }
3175
3176
3177 bool LyXParagraph::RoffContTableRows(FILE *fp, int i, int actcell)
3178 {
3179         if (!table)
3180                 return false;
3181
3182         LyXFont
3183                 font1 = LyXFont(LyXFont::ALL_INHERIT),
3184                 font2;
3185         Inset
3186                 *inset;
3187         int
3188                 lastpos, cell;
3189         char
3190                 c;
3191         LString
3192                 fname2;
3193         FILE
3194                 *fp2;
3195
3196         fname2 = TmpFileName(LString(),"RAT2");
3197         lastpos = i;
3198         cell = table->CellHasContRow(actcell);
3199         actcell++;
3200         while(cell >= 0) {
3201                 // first find the right position
3202                 i = lastpos;
3203                 for (; (i<last) && (actcell<cell); i++) {
3204                         c = GetChar(i);
3205                         if (c == LYX_META_NEWLINE)
3206                                 actcell++;
3207                 }
3208                 lastpos = i;
3209                 c=GetChar(i);
3210                 if ((c != ' ') && (c != LYX_META_NEWLINE))
3211                         fprintf(fp," ");
3212                 for (; (i < last) && ((c=GetChar(i)) != LYX_META_NEWLINE); i++) {
3213                         font2 = GetFontSettings(i);
3214                         if (font1.latex() != font2.latex()) {
3215                                 if (font2.latex() != LyXFont::OFF)
3216                                         continue;
3217                         }
3218                         c = GetChar(i);
3219                         switch (c) {
3220                         case LYX_META_INSET:
3221                                 if ((inset = GetInset(i))) {
3222                                         if (!(fp2=fopen(fname2.c_str(),"w+"))) {
3223                                                 WriteAlert(_("LYX_ERROR:"), _("Cannot open temporary file:"), fname2);
3224                                                 return false;
3225                                         }
3226                                         inset->Latex(fp2,-1);
3227                                         rewind(fp2);
3228                                         c = fgetc(fp2);
3229                                         while(!feof(fp2)) {
3230                                                 if (c == '\\')
3231                                                         fprintf(fp,"\\\\");
3232                                                 else
3233                                                         fputc(c,fp);
3234                                                 c = fgetc(fp2);
3235                                         }
3236                                         fclose(fp2);
3237                                 }
3238                                 break;
3239                         case LYX_META_NEWLINE:
3240                                 break;
3241                         case LYX_META_HFILL: 
3242                                 break;
3243                         case LYX_META_PROTECTED_SEPARATOR:
3244                                 break;
3245                         case '\\': 
3246                                 fprintf(fp, "\\\\");
3247                                 break;
3248                         default:
3249                                 if (c != '\0')
3250                                         fprintf(fp, "%c", c);
3251                                 else
3252                                         lyxerr.debug("RoffAsciiTable: NULL char in structure.");
3253                                 break;
3254                         }
3255                 }
3256                 cell = table->CellHasContRow(actcell);
3257         }
3258         return true;
3259 }
3260
3261 LyXParagraph * LyXParagraph::TeXDeeper(LString &file, TexRow &texrow,
3262                                        LString &foot, TexRow &foot_texrow,
3263                                        int &foot_count)
3264 {
3265         lyxerr.debug(LString("TeXDeeper...     ") + (long)this, Error::LATEX);
3266         LyXParagraph *par = this;
3267
3268         while (par && par->depth == depth) {
3269                 if (par->IsDummy())
3270                         lyxerr.print("ERROR (LyXParagraph::TeXDeeper)");
3271                 if (lyxstyle.Style(GetCurrentTextClass(), 
3272                                    par->layout)->isEnvironment()
3273                     || par->pextra_type != PEXTRA_NONE) 
3274                         {
3275                                 par = par->TeXEnvironment(file, texrow,
3276                                                           foot, foot_texrow,
3277                                                           foot_count);
3278                         } else {
3279                                 par = par->TeXOnePar(file, texrow,
3280                                                      foot, foot_texrow,
3281                                                      foot_count);
3282                         }
3283         }
3284         lyxerr.debug(LString("TeXDeeper...done ") + (long)par, Error::LATEX);
3285
3286         return par;
3287 }
3288
3289
3290 LyXParagraph* LyXParagraph::TeXEnvironment(LString &file, TexRow &texrow,
3291                                            LString &foot, TexRow &foot_texrow,
3292                                            int &foot_count)
3293 {
3294         bool
3295                 eindent_open = false;
3296         bool
3297                 foot_this_level = false;
3298                 // flags when footnotetext should be appended to file.
3299         static bool
3300                 minipage_open = false;
3301         static int
3302                 minipage_open_depth = 0;
3303         char
3304                 par_sep = current_view->currentBuffer()->params.paragraph_separation;
3305     
3306         lyxerr.debug(LString("TeXEnvironment...     ") + long(this), Error::LATEX);
3307         if (IsDummy())
3308                 lyxerr.print("ERROR (LyXParagraph::TeXEnvironment)");
3309
3310         LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), layout);
3311        
3312         if (pextra_type == PEXTRA_INDENT) {
3313                 if (!pextra_width.empty()) {
3314                         file += "\\begin{LyXParagraphIndent}{"
3315                                 + pextra_width + "}\n";
3316                 } else {
3317                         //float ib = atof(pextra_widthp.c_str())/100;
3318                         // LString can't handle floats at present (971109)
3319                         // so I'll do a conversion by hand knowing that
3320                         // the limits are 0.0 to 1.0. ARRae.
3321                         file += "\\begin{LyXParagraphIndent}{";
3322                         switch (pextra_widthp.length()) {
3323                         case 3:
3324                                 file += "1.00";
3325                                 break;
3326                         case 2:
3327                                 file += "0.";
3328                                 file += pextra_widthp;
3329                                 break;
3330                         case 1:
3331                                 file += "0.0";
3332                                 file += pextra_widthp;
3333                         }
3334                         file += "\\columnwidth}\n";
3335                 }
3336                 texrow.newline();
3337                 eindent_open = true;
3338         }
3339         if ((pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3340                 if (pextra_hfill && Previous() &&
3341                     (Previous()->pextra_type == PEXTRA_MINIPAGE)) {
3342                         file += "\\hfill{}\n";
3343                         texrow.newline();
3344                 }
3345                 if (par_sep == LYX_PARSEP_INDENT) {
3346                         file += "{\\setlength\\parindent{0pt}\n";
3347                         texrow.newline();
3348                 }
3349                 file += "\\begin{minipage}";
3350                 switch(pextra_alignment) {
3351                 case MINIPAGE_ALIGN_TOP:
3352                         file += "[t]";
3353                         break;
3354                 case MINIPAGE_ALIGN_MIDDLE:
3355                         file += "[m]";
3356                         break;
3357                 case MINIPAGE_ALIGN_BOTTOM:
3358                         file += "[b]";
3359                         break;
3360                 }
3361                 if (!pextra_width.empty()) {
3362                         file += '{';
3363                         file += pextra_width + "}\n";
3364                 } else {
3365                         //float ib = atof(par->pextra_width.c_str())/100;
3366                         // LString can't handle floats at present
3367                         // so I'll do a conversion by hand knowing that
3368                         // the limits are 0.0 to 1.0. ARRae.
3369                         file += '{';
3370                         switch (pextra_widthp.length()) {
3371                         case 3:
3372                                 file += "1.00";
3373                                 break;
3374                         case 2:
3375                                 file += "0.";
3376                                 file += pextra_widthp;
3377                                 break;
3378                         case 1:
3379                                 file += "0.0";
3380                                 file += pextra_widthp;
3381                         }
3382                         file += "\\columnwidth}\n";
3383                 }
3384                 texrow.newline();
3385                 if (par_sep == LYX_PARSEP_INDENT) {
3386                         file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3387                         texrow.newline();
3388                 }
3389                 minipage_open = true;
3390                 minipage_open_depth = depth;
3391         }
3392
3393 #ifdef WITH_WARNINGS
3394 #warning Define FANCY_FOOTNOTE_CODE to re-enable Allan footnote code
3395         //I disabled it because it breaks when lists span on several
3396         //pages (JMarc)
3397 #endif
3398         if (style->isEnvironment()){
3399                 if (style->latextype == LATEX_LIST_ENVIRONMENT) {
3400 #ifdef FANCY_FOOTNOTE_CODE
3401                         if (foot_count < 0) {
3402                                 // flag that footnote[mark][text] should be
3403                                 // used for any footnotes from now on
3404                                 foot_count = 0;
3405                                 foot_this_level = true;
3406                         }
3407 #endif
3408                         file += "\\begin{" + style->latexname + "}{"
3409                                 + labelwidthstring + "}\n";
3410                 } else if (style->labeltype == LABEL_BIBLIO) {
3411                         // ale970405
3412                         file += "\\begin{" + style->latexname + "}{"
3413                                 + bibitemWidthest() + "}\n";
3414                 } else if (style->latextype == LATEX_ITEM_ENVIRONMENT) {
3415 #ifdef FANCY_FOOTNOTE_CODE
3416                         if (foot_count < 0) {
3417                                 // flag that footnote[mark][text] should be
3418                                 // used for any footnotes from now on
3419                                 foot_count = 0;
3420                                 foot_this_level = true;
3421                         }
3422 #endif
3423                         file += "\\begin{" + style->latexname + '}'
3424                                 + style->latexparam + '\n';
3425                 } else 
3426                         file += "\\begin{" + style->latexname + '}'
3427                                 + style->latexparam + '\n';
3428                 texrow.newline();
3429         }
3430         LyXParagraph *par = this;
3431         do {
3432                 par = par->TeXOnePar(file, texrow,
3433                                      foot, foot_texrow, foot_count);
3434 #if 0
3435                 if (eindent_open && par && par->pextra_type != PEXTRA_INDENT) {
3436                         file += "\\end{LyXParagraphIndent}\n";
3437                         texrow.newline();
3438                         eindent_open = false;
3439                         if (!style->isEnvironment())
3440                                 break;
3441                 }
3442 #endif
3443                 if (minipage_open && par && !style->isEnvironment() &&
3444                     (par->pextra_type == PEXTRA_MINIPAGE) &&
3445                     par->pextra_start_minipage) {
3446                     file += "\\end{minipage}\n";
3447                     texrow.newline();
3448                     if (par_sep == LYX_PARSEP_INDENT) {
3449                         file += "}\n";
3450                         texrow.newline();
3451                     }
3452                     minipage_open = false;
3453                 }
3454                 if (par && par->depth > depth) {
3455                         if (lyxstyle.Style(GetCurrentTextClass(),
3456                                            par->layout)->isParagraph()
3457                             && !par->table
3458                             && !file.suffixIs("\n\n")) {
3459                             // There should be at least one '\n' already
3460                             // but we need there to be two for Standard 
3461                             // paragraphs that are depth-increment'ed to be
3462                             // output correctly.  However, tables can also be
3463                             // paragraphs so don't adjust them.  ARRae
3464                                 file += '\n';
3465                                 texrow.newline();
3466                         }
3467                         par = par->TeXDeeper(file, texrow,
3468                                              foot, foot_texrow, foot_count);
3469                 }
3470                 if (par && par->layout == layout && par->depth == depth &&
3471                     (par->pextra_type == PEXTRA_MINIPAGE) && !minipage_open) {
3472                         if (par->pextra_hfill && par->Previous() &&
3473                             (par->Previous()->pextra_type == PEXTRA_MINIPAGE)){
3474                                 file += "\\hfill{}\n";
3475                                 texrow.newline();
3476                         }
3477 //                      else
3478 //                              file += '\n';
3479                         if (par_sep == LYX_PARSEP_INDENT) {
3480                                 file += "{\\setlength\\parindent{0pt}\n";
3481                                 texrow.newline();
3482                         }
3483                         file += "\\begin{minipage}";
3484                         switch(par->pextra_alignment) {
3485                         case MINIPAGE_ALIGN_TOP:
3486                                 file += "[t]";
3487                                 break;
3488                         case MINIPAGE_ALIGN_MIDDLE:
3489                                 file += "[m]";
3490                                 break;
3491                         case MINIPAGE_ALIGN_BOTTOM:
3492                                 file += "[b]";
3493                                 break;
3494                         }
3495                         if (!par->pextra_width.empty()) {
3496                                 file += '{';
3497                                 file += par->pextra_width;
3498                                 file += "}\n";
3499                         } else {
3500                                 //float ib = atof(par->pextra_widthp.c_str())/100;
3501                                 // LString can't handle floats at present
3502                                 // so I'll do a conversion by hand knowing that
3503                                 // the limits are 0.0 to 1.0. ARRae.
3504                                 file += '{';
3505                                 switch (par->pextra_widthp.length()) {
3506                                 case 3:
3507                                         file += "1.00";
3508                                         break;
3509                                 case 2:
3510                                         file += "0.";
3511                                         file += par->pextra_widthp;
3512                                         break;
3513                                 case 1:
3514                                         file += "0.0";
3515                                         file += par->pextra_widthp;
3516                                 }
3517                                 file += "\\columnwidth}\n";
3518                         }
3519                         texrow.newline();
3520                         if (par_sep == LYX_PARSEP_INDENT) {
3521                                 file += "\\setlength\\parindent{\\LyXMinipageIndent}\n";
3522                                 texrow.newline();
3523                         }
3524                         minipage_open = true;
3525                         minipage_open_depth = par->depth;
3526                 }
3527         } while (par
3528                  && par->layout == layout
3529                  && par->depth == depth
3530                  && par->pextra_type == pextra_type);
3531  
3532         if (style->isEnvironment()) {
3533                 file += "\\end{" + style->latexname + '}';
3534                 // maybe this should go after the minipage closes?
3535                 if (foot_this_level) {
3536                         if (foot_count >= 1) {
3537                                 if (foot_count > 1) {
3538                                         file += "\\addtocounter{footnote}{-";
3539                                         file += foot_count - 1;
3540                                         file += '}';
3541                                 }
3542                                 file += foot;
3543                                 texrow += foot_texrow;
3544                                 foot.clean();
3545                                 foot_texrow.reset();
3546                                 foot_count = 0;
3547                         }
3548                 }
3549         }
3550         if (minipage_open && (minipage_open_depth == depth) &&
3551             (!par || par->pextra_start_minipage ||
3552              par->pextra_type != PEXTRA_MINIPAGE)) {
3553                 file += "\\end{minipage}\n";
3554                 texrow.newline();
3555                 if (par_sep == LYX_PARSEP_INDENT) {
3556                         file += "}\n";
3557                         texrow.newline();
3558                 }
3559                 if (par && par->pextra_type != PEXTRA_MINIPAGE) {
3560                         file += "\\medskip\n\n";
3561                         texrow.newline();
3562                         texrow.newline();
3563                 }
3564                 minipage_open = false;
3565         }
3566         if (eindent_open) {
3567                 file += "\\end{LyXParagraphIndent}\n";
3568                 texrow.newline();
3569         }
3570 //      if (tex_code_break_column){
3571         if (!(par && (par->pextra_type==PEXTRA_MINIPAGE) 
3572               && par->pextra_hfill)) {
3573                 file += '\n';
3574                 texrow.newline();
3575         }
3576         lyxerr.debug(LString("TeXEnvironment...done ") 
3577                      + (long)par, Error::LATEX);
3578         return par;  // ale970302
3579 }
3580
3581
3582 LyXParagraph * LyXParagraph::TeXFootnote(LString &file, TexRow &texrow,
3583                                          LString &foot, TexRow &foot_texrow,
3584                                          int &foot_count)
3585 {
3586         lyxerr.debug(LString("TeXFootnote...     ") 
3587                      + (long)this, Error::LATEX);
3588         if (footnoteflag == LyXParagraph::NO_FOOTNOTE)
3589                 lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
3590                              "No footnote!");
3591
3592         LyXParagraph *par = this;
3593         LyXLayout * style = lyxstyle.Style(GetCurrentTextClass(), 
3594                                            previous->GetLayout());
3595         
3596         if (style->needprotect && footnotekind != LyXParagraph::FOOTNOTE){
3597                 lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
3598                              "Float other than footnote in command"
3599                              " with moving argument is illegal");
3600         }
3601
3602         if (footnotekind != LyXParagraph::FOOTNOTE
3603             && footnotekind != LyXParagraph::MARGIN
3604             && file.length()
3605             && !file.suffixIs('\n')) {
3606                 // we need to ensure that real floats like tables and figures
3607                 // have their \begin{} on a new line otherwise we can get
3608                 // incorrect results when using the endfloat.sty package
3609                 // especially if two floats follow one another.  ARRae 981022
3610                 // NOTE: if the file is length 0 it must have just been
3611                 //       written out so we assume it ended with a '\n'
3612                 file += '\n';
3613                 texrow.newline();
3614         }
3615         
3616         BufferParams *params = &current_view->currentBuffer()->params;
3617         bool footer_in_body = true;
3618         switch (footnotekind) {
3619         case LyXParagraph::FOOTNOTE:
3620                 if (style->intitle) {
3621                         file += "\\thanks{\n";
3622                         footer_in_body = false;
3623                 } else {
3624                         if (foot_count == -1) {
3625                                 // we're at depth 0 so we can use:
3626                                 file += "\\footnote{%\n";
3627                                 footer_in_body = false;
3628                         } else {
3629                                 file += "\\footnotemark{}%\n";
3630                                 if (foot_count) {
3631                                         // we only need this when there are
3632                                         // multiple footnotes
3633                                         foot += "\\stepcounter{footnote}";
3634                                 }
3635                                 foot += "\\footnotetext{%\n";
3636                                 foot_texrow.start(this,0);
3637                                 foot_texrow.newline();
3638                                 ++foot_count;
3639                         }
3640                 }
3641                 break;
3642         case LyXParagraph::MARGIN:
3643                 file += "\\marginpar{\n";
3644                 break;
3645         case LyXParagraph::FIG:
3646                 if (pextra_type == PEXTRA_FLOATFLT
3647                     && (!pextra_width.empty()
3648                         || !pextra_widthp.empty())) {
3649                         char bufr[80];
3650                         if (!pextra_width.empty())
3651                                 sprintf(bufr, "\\begin{floatingfigure}{%s}\n",
3652                                         pextra_width.c_str());
3653                         else
3654                                 sprintf(bufr, "\\begin{floatingfigure}{%f\\textwidth}\n",
3655                                         atoi(pextra_widthp.c_str())/100.0);
3656                         file += bufr;
3657                 } else {
3658                         file += "\\begin{figure}";
3659                         if (!params->float_placement.empty()) { 
3660                                 file += '[';
3661                                 file += params->float_placement;
3662                                 file += "]\n";
3663                         } else {
3664                                 file += '\n';
3665                         }
3666                 }
3667                 break;
3668         case LyXParagraph::TAB:
3669                 file += "\\begin{table}";
3670                 if (!params->float_placement.empty()) { 
3671                         file += '[';
3672                         file += params->float_placement;
3673                         file += "]\n";
3674                 } else {
3675                         file += '\n';
3676                 }
3677                 break;
3678         case LyXParagraph::WIDE_FIG:
3679                 file += "\\begin{figure*}";
3680                 if (!params->float_placement.empty()) { 
3681                         file += '[';
3682                         file += params->float_placement;
3683                         file += "]\n";
3684                 } else {
3685                         file += '\n';
3686                 }
3687                 break;
3688         case LyXParagraph::WIDE_TAB:
3689                 file += "\\begin{table*}";
3690                 if (!params->float_placement.empty()) { 
3691                         file += '[';
3692                         file += params->float_placement;
3693                         file += "]\n";
3694                 } else {
3695                         file += '\n';
3696                 }
3697                 break;
3698         case LyXParagraph::ALGORITHM:
3699                 file += "\\begin{algorithm}\n";
3700                 break;
3701         }
3702         texrow.newline();
3703    
3704         if (footnotekind != LyXParagraph::FOOTNOTE
3705             || !footer_in_body) {
3706                 // Process text for all floats except footnotes in body
3707                 do {
3708                         LyXLayout *style = lyxstyle.Style(GetCurrentTextClass(),
3709                                                           par->layout);
3710                         if (par->IsDummy())
3711                                 lyxerr.print("ERROR (LyXParagraph::TeXFootnote)");
3712                         if (style->isEnvironment()
3713                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3714                                 // Allows the use of minipages within float environments.
3715                                 // Shouldn't be circular because we don't support
3716                                 // footnotes inside floats (yet). ARRae
3717                                 par = par->TeXEnvironment(file, texrow,
3718                                                           foot, foot_texrow,
3719                                                           foot_count);
3720                         } else {
3721                                 par = par->TeXOnePar(file, texrow,
3722                                                      foot, foot_texrow,
3723                                                      foot_count);
3724                         }
3725                         
3726                         if (par && !par->IsDummy() && par->depth > depth) {
3727                                 par = par->TeXDeeper(file, texrow,
3728                                                      foot, foot_texrow,
3729                                                      foot_count);
3730                         }
3731                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3732         } else {
3733                 // process footnotes > depth 0 or in environments separately
3734                 // NOTE: Currently don't support footnotes within footnotes
3735                 //       even though that is possible using the \footnotemark
3736                 LString dummy;
3737                 TexRow dummy_texrow;
3738                 int dummy_count = 0;
3739                 do {
3740                         LyXLayout *style = lyxstyle.Style(GetCurrentTextClass(),
3741                                                           par->layout);
3742                         if (par->IsDummy())
3743                                 lyxerr.print("ERROR (LyXParagraph::TeXFootnote)");
3744                         if (style->isEnvironment()
3745                             || par->pextra_type == PEXTRA_MINIPAGE) { /* && !minipage_open ?? */
3746                                 // Allows the use of minipages within float environments.
3747                                 // Shouldn't be circular because we don't support
3748                                 // footnotes inside floats (yet). ARRae
3749                                 par = par->TeXEnvironment(foot, foot_texrow,
3750                                                           dummy, dummy_texrow,
3751                                                           dummy_count);
3752                         } else {
3753                                 par = par->TeXOnePar(foot, foot_texrow,
3754                                                      dummy, dummy_texrow,
3755                                                      dummy_count);
3756                         }
3757
3758                         if (par && !par->IsDummy() && par->depth > depth) {
3759                                 par = par->TeXDeeper(foot, foot_texrow,
3760                                                      dummy, dummy_texrow,
3761                                                      dummy_count);
3762                         }
3763                 } while (par && par->footnoteflag != LyXParagraph::NO_FOOTNOTE);
3764                 if (dummy_count) {
3765                         lyxerr.print("ERROR (LyXParagraph::TeXFootnote): "
3766                                      "Footnote in a Footnote -- not supported");
3767                 }
3768         }
3769
3770         switch (footnotekind) {
3771         case LyXParagraph::FOOTNOTE:
3772                 if (footer_in_body) {
3773                         // This helps tell which of the multiple
3774                         // footnotetexts an error was in.
3775                         foot += "}%\n";
3776                         foot_texrow.newline();
3777                 } else {
3778                         file += '}';
3779                 }
3780                 break;
3781         case LyXParagraph::MARGIN:
3782                 file += '}';
3783                 break;
3784         case LyXParagraph::FIG:
3785                 if (pextra_type == PEXTRA_FLOATFLT
3786                     && (!pextra_width.empty()
3787                         || !pextra_widthp.empty()))
3788                         file += "\\end{floatingfigure}";
3789                 else
3790                         file += "\\end{figure}";
3791                 break;
3792         case LyXParagraph::TAB:
3793                 file += "\\end{table}";
3794                 break;
3795         case LyXParagraph::WIDE_FIG:
3796                 file += "\\end{figure*}";
3797                 break;
3798         case LyXParagraph::WIDE_TAB:
3799                 file += "\\end{table*}";
3800                 break;
3801         case LyXParagraph::ALGORITHM:
3802                 file += "\\end{algorithm}";
3803                 break;
3804         }
3805
3806         if (footnotekind != LyXParagraph::FOOTNOTE
3807             && footnotekind != LyXParagraph::MARGIN) {
3808                 // we need to ensure that real floats like tables and figures
3809                 // have their \end{} on a line of their own otherwise we can
3810                 // get incorrect results when using the endfloat.sty package.
3811                 file += "\n";
3812                 texrow.newline();
3813         }
3814
3815         lyxerr.debug(LString("TeXFootnote...done ") +
3816                      long(par->next), Error::LATEX);
3817         return par;
3818 }
3819
3820
3821 void LyXParagraph::SetPExtraType(int type, const char *width,const char *widthp)
3822 {
3823     pextra_type = type;
3824     pextra_width = width;
3825     pextra_widthp = widthp;
3826
3827     if (lyxstyle.Style(GetCurrentTextClass(), 
3828                        layout)->isEnvironment()) {
3829         LyXParagraph
3830             *par = this,
3831             *ppar = par;
3832
3833         while (par && (par->layout == layout) && (par->depth == depth)) {
3834             ppar = par;
3835             par = par->Previous();
3836             if (par)
3837                 par = par->FirstPhysicalPar();
3838             while (par && par->depth > depth) {
3839                 par = par->Previous();
3840                 if (par)
3841                     par = par->FirstPhysicalPar();
3842             }
3843         }
3844         par = ppar;
3845         while (par && (par->layout == layout) && (par->depth == depth)) {
3846             par->pextra_type = type;
3847             par->pextra_width = width;
3848             par->pextra_widthp = widthp;
3849             par = par->NextAfterFootnote();
3850             if (par && (par->depth > depth))
3851                 par->SetPExtraType(type,width,widthp);
3852             while (par && ((par->depth > depth) || par->IsDummy()))
3853                 par = par->NextAfterFootnote();
3854         }
3855     }
3856 }
3857
3858 void LyXParagraph::UnsetPExtraType()
3859 {
3860     if (pextra_type == PEXTRA_NONE)
3861         return;
3862     
3863     pextra_type = PEXTRA_NONE;
3864     pextra_width.clean();
3865     pextra_widthp.clean();
3866
3867     if (lyxstyle.Style(GetCurrentTextClass(), 
3868                        layout)->isEnvironment()) {
3869         LyXParagraph
3870             *par = this,
3871             *ppar = par;
3872
3873         while (par && (par->layout == layout) && (par->depth == depth)) {
3874             ppar = par;
3875             par = par->Previous();
3876             if (par)
3877                 par = par->FirstPhysicalPar();
3878             while (par && par->depth > depth) {
3879                 par = par->Previous();
3880                 if (par)
3881                     par = par->FirstPhysicalPar();
3882             }
3883         }
3884         par = ppar;
3885         while (par && (par->layout == layout) && (par->depth == depth)) {
3886             par->pextra_type = PEXTRA_NONE;
3887             par->pextra_width.clean();
3888             par->pextra_widthp.clean();
3889             par = par->NextAfterFootnote();
3890             if (par && (par->depth > depth))
3891                 par->UnsetPExtraType();
3892             while (par && ((par->depth > depth) || par->IsDummy()))
3893                 par = par->NextAfterFootnote();
3894         }
3895     }
3896 }