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